mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Rewrite the AppDependencies system.
This commit is contained in:
committed by
Cody Henthorne
parent
a0131bf39b
commit
b6a4e1f145
@@ -0,0 +1,346 @@
|
||||
package org.thoughtcrime.securesms.dependencies
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.annotation.MainThread
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||
import io.reactivex.rxjava3.subjects.Subject
|
||||
import okhttp3.OkHttpClient
|
||||
import org.signal.core.util.concurrent.DeadlockDetector
|
||||
import org.signal.core.util.resettableLazy
|
||||
import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations
|
||||
import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations
|
||||
import org.thoughtcrime.securesms.components.TypingStatusRepository
|
||||
import org.thoughtcrime.securesms.components.TypingStatusSender
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl
|
||||
import org.thoughtcrime.securesms.database.DatabaseObserver
|
||||
import org.thoughtcrime.securesms.database.PendingRetryReceiptCache
|
||||
import org.thoughtcrime.securesms.groups.GroupsV2Authorization
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager
|
||||
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository
|
||||
import org.thoughtcrime.securesms.messages.IncomingMessageObserver
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier
|
||||
import org.thoughtcrime.securesms.payments.Payments
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipientCache
|
||||
import org.thoughtcrime.securesms.revealable.ViewOnceMessageManager
|
||||
import org.thoughtcrime.securesms.service.DeletedCallEventManager
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager
|
||||
import org.thoughtcrime.securesms.service.ExpiringStoriesManager
|
||||
import org.thoughtcrime.securesms.service.PendingRetryReceiptManager
|
||||
import org.thoughtcrime.securesms.service.ScheduledMessageManager
|
||||
import org.thoughtcrime.securesms.service.TrimThreadsByDateManager
|
||||
import org.thoughtcrime.securesms.service.webrtc.SignalCallManager
|
||||
import org.thoughtcrime.securesms.shakereport.ShakeToReport
|
||||
import org.thoughtcrime.securesms.util.AppForegroundObserver
|
||||
import org.thoughtcrime.securesms.util.EarlyMessageCache
|
||||
import org.thoughtcrime.securesms.util.FrameRateTracker
|
||||
import org.thoughtcrime.securesms.video.exo.GiphyMp4Cache
|
||||
import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool
|
||||
import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager
|
||||
import org.whispersystems.signalservice.api.SignalServiceDataStore
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
||||
import org.whispersystems.signalservice.api.SignalWebSocket
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
|
||||
import org.whispersystems.signalservice.api.services.CallLinksService
|
||||
import org.whispersystems.signalservice.api.services.DonationsService
|
||||
import org.whispersystems.signalservice.api.services.ProfileService
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration
|
||||
import org.whispersystems.signalservice.internal.websocket.LibSignalNetwork
|
||||
import java.util.function.Supplier
|
||||
|
||||
/**
|
||||
* Location for storing and retrieving application-scoped singletons. Users must call
|
||||
* [.init] before using any of the methods, preferably early on in
|
||||
* [Application.onCreate].
|
||||
*
|
||||
* All future application-scoped singletons should be written as normal objects, then placed here
|
||||
* to manage their singleton-ness.
|
||||
*/
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object AppDependencies {
|
||||
private lateinit var _application: Application
|
||||
private lateinit var provider: Provider
|
||||
|
||||
// Needs special initialization because it needs to be created on the main thread
|
||||
private lateinit var _appForegroundObserver: AppForegroundObserver
|
||||
|
||||
@JvmStatic
|
||||
@MainThread
|
||||
fun init(application: Application, provider: Provider) {
|
||||
if (this::_application.isInitialized || this::provider.isInitialized) {
|
||||
throw IllegalStateException("Already initialized!")
|
||||
}
|
||||
|
||||
_application = application
|
||||
AppDependencies.provider = provider
|
||||
|
||||
_appForegroundObserver = provider.provideAppForegroundObserver()
|
||||
_appForegroundObserver.begin()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val isInitialized: Boolean
|
||||
get() = this::_application.isInitialized
|
||||
|
||||
@JvmStatic
|
||||
val application: Application
|
||||
get() = _application
|
||||
|
||||
@JvmStatic
|
||||
val appForegroundObserver: AppForegroundObserver
|
||||
get() = _appForegroundObserver
|
||||
|
||||
@JvmStatic
|
||||
val recipientCache: LiveRecipientCache by lazy {
|
||||
provider.provideRecipientCache()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val jobManager: JobManager by lazy {
|
||||
provider.provideJobManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val frameRateTracker: FrameRateTracker by lazy {
|
||||
provider.provideFrameRateTracker()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val megaphoneRepository: MegaphoneRepository by lazy {
|
||||
provider.provideMegaphoneRepository()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val earlyMessageCache: EarlyMessageCache by lazy {
|
||||
provider.provideEarlyMessageCache()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val typingStatusRepository: TypingStatusRepository by lazy {
|
||||
provider.provideTypingStatusRepository()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val typingStatusSender: TypingStatusSender by lazy {
|
||||
provider.provideTypingStatusSender()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val databaseObserver: DatabaseObserver by lazy {
|
||||
provider.provideDatabaseObserver()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val trimThreadsByDateManager: TrimThreadsByDateManager by lazy {
|
||||
provider.provideTrimThreadsByDateManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val viewOnceMessageManager: ViewOnceMessageManager by lazy {
|
||||
provider.provideViewOnceMessageManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val expiringMessageManager: ExpiringMessageManager by lazy {
|
||||
provider.provideExpiringMessageManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val deletedCallEventManager: DeletedCallEventManager by lazy {
|
||||
provider.provideDeletedCallEventManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val signalCallManager: SignalCallManager by lazy {
|
||||
provider.provideSignalCallManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val shakeToReport: ShakeToReport by lazy {
|
||||
provider.provideShakeToReport()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val pendingRetryReceiptManager: PendingRetryReceiptManager by lazy {
|
||||
provider.providePendingRetryReceiptManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val pendingRetryReceiptCache: PendingRetryReceiptCache by lazy {
|
||||
provider.providePendingRetryReceiptCache()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val messageNotifier: MessageNotifier by lazy {
|
||||
provider.provideMessageNotifier()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val giphyMp4Cache: GiphyMp4Cache by lazy {
|
||||
provider.provideGiphyMp4Cache()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val exoPlayerPool: SimpleExoPlayerPool by lazy {
|
||||
provider.provideExoPlayerPool()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val deadlockDetector: DeadlockDetector by lazy {
|
||||
provider.provideDeadlockDetector()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val expireStoriesManager: ExpiringStoriesManager by lazy {
|
||||
provider.provideExpiringStoriesManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val scheduledMessageManager: ScheduledMessageManager by lazy {
|
||||
provider.provideScheduledMessageManager()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val androidCallAudioManager: AudioManagerCompat by lazy {
|
||||
provider.provideAndroidCallAudioManager()
|
||||
}
|
||||
|
||||
private val _webSocketObserver: Subject<WebSocketConnectionState> = BehaviorSubject.create()
|
||||
|
||||
/**
|
||||
* An observable that emits the current state of the WebSocket connection across the various lifecycles
|
||||
* of the [signalWebSocket].
|
||||
*/
|
||||
@JvmStatic
|
||||
val webSocketObserver: Observable<WebSocketConnectionState> = _webSocketObserver
|
||||
|
||||
private val _networkModule = resettableLazy {
|
||||
NetworkDependenciesModule(application, provider, _webSocketObserver)
|
||||
}
|
||||
private val networkModule by _networkModule
|
||||
|
||||
@JvmStatic
|
||||
val signalServiceNetworkAccess: SignalServiceNetworkAccess
|
||||
get() = networkModule.signalServiceNetworkAccess
|
||||
|
||||
@JvmStatic
|
||||
val protocolStore: SignalServiceDataStoreImpl
|
||||
get() = networkModule.protocolStore
|
||||
|
||||
@JvmStatic
|
||||
val signalServiceMessageSender: SignalServiceMessageSender
|
||||
get() = networkModule.signalServiceMessageSender
|
||||
|
||||
@JvmStatic
|
||||
val signalServiceAccountManager: SignalServiceAccountManager
|
||||
get() = networkModule.signalServiceAccountManager
|
||||
|
||||
@JvmStatic
|
||||
val signalServiceMessageReceiver: SignalServiceMessageReceiver
|
||||
get() = networkModule.signalServiceMessageReceiver
|
||||
|
||||
@JvmStatic
|
||||
val incomingMessageObserver: IncomingMessageObserver
|
||||
get() = networkModule.incomingMessageObserver
|
||||
|
||||
@JvmStatic
|
||||
val libsignalNetwork: LibSignalNetwork
|
||||
get() = networkModule.libsignalNetwork
|
||||
|
||||
@JvmStatic
|
||||
val signalWebSocket: SignalWebSocket
|
||||
get() = networkModule.signalWebSocket
|
||||
|
||||
@JvmStatic
|
||||
val groupsV2Authorization: GroupsV2Authorization
|
||||
get() = networkModule.groupsV2Authorization
|
||||
|
||||
@JvmStatic
|
||||
val groupsV2Operations: GroupsV2Operations
|
||||
get() = networkModule.groupsV2Operations
|
||||
|
||||
@JvmStatic
|
||||
val clientZkReceiptOperations
|
||||
get() = networkModule.clientZkReceiptOperations
|
||||
|
||||
@JvmStatic
|
||||
val payments: Payments
|
||||
get() = networkModule.payments
|
||||
|
||||
@JvmStatic
|
||||
val callLinksService: CallLinksService
|
||||
get() = networkModule.callLinksService
|
||||
|
||||
@JvmStatic
|
||||
val profileService: ProfileService
|
||||
get() = networkModule.profileService
|
||||
|
||||
@JvmStatic
|
||||
val donationsService: DonationsService
|
||||
get() = networkModule.donationsService
|
||||
|
||||
@JvmStatic
|
||||
val okHttpClient: OkHttpClient
|
||||
get() = networkModule.okHttpClient
|
||||
|
||||
@JvmStatic
|
||||
val signalOkHttpClient: OkHttpClient
|
||||
get() = networkModule.signalOkHttpClient
|
||||
|
||||
@JvmStatic
|
||||
fun resetProtocolStores() {
|
||||
networkModule.resetProtocolStores()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun resetNetwork() {
|
||||
networkModule.closeConnections()
|
||||
_networkModule.reset()
|
||||
}
|
||||
|
||||
interface Provider {
|
||||
fun provideGroupsV2Operations(signalServiceConfiguration: SignalServiceConfiguration): GroupsV2Operations
|
||||
fun provideSignalServiceAccountManager(signalServiceConfiguration: SignalServiceConfiguration, groupsV2Operations: GroupsV2Operations): SignalServiceAccountManager
|
||||
fun provideSignalServiceMessageSender(signalWebSocket: SignalWebSocket, protocolStore: SignalServiceDataStore, signalServiceConfiguration: SignalServiceConfiguration): SignalServiceMessageSender
|
||||
fun provideSignalServiceMessageReceiver(signalServiceConfiguration: SignalServiceConfiguration): SignalServiceMessageReceiver
|
||||
fun provideSignalServiceNetworkAccess(): SignalServiceNetworkAccess
|
||||
fun provideRecipientCache(): LiveRecipientCache
|
||||
fun provideJobManager(): JobManager
|
||||
fun provideFrameRateTracker(): FrameRateTracker
|
||||
fun provideMegaphoneRepository(): MegaphoneRepository
|
||||
fun provideEarlyMessageCache(): EarlyMessageCache
|
||||
fun provideMessageNotifier(): MessageNotifier
|
||||
fun provideIncomingMessageObserver(): IncomingMessageObserver
|
||||
fun provideTrimThreadsByDateManager(): TrimThreadsByDateManager
|
||||
fun provideViewOnceMessageManager(): ViewOnceMessageManager
|
||||
fun provideExpiringStoriesManager(): ExpiringStoriesManager
|
||||
fun provideExpiringMessageManager(): ExpiringMessageManager
|
||||
fun provideDeletedCallEventManager(): DeletedCallEventManager
|
||||
fun provideTypingStatusRepository(): TypingStatusRepository
|
||||
fun provideTypingStatusSender(): TypingStatusSender
|
||||
fun provideDatabaseObserver(): DatabaseObserver
|
||||
fun providePayments(signalServiceAccountManager: SignalServiceAccountManager): Payments
|
||||
fun provideShakeToReport(): ShakeToReport
|
||||
fun provideAppForegroundObserver(): AppForegroundObserver
|
||||
fun provideSignalCallManager(): SignalCallManager
|
||||
fun providePendingRetryReceiptManager(): PendingRetryReceiptManager
|
||||
fun providePendingRetryReceiptCache(): PendingRetryReceiptCache
|
||||
fun provideSignalWebSocket(signalServiceConfigurationSupplier: Supplier<SignalServiceConfiguration>, libSignalNetworkSupplier: Supplier<LibSignalNetwork?>): SignalWebSocket
|
||||
fun provideProtocolStore(): SignalServiceDataStoreImpl
|
||||
fun provideGiphyMp4Cache(): GiphyMp4Cache
|
||||
fun provideExoPlayerPool(): SimpleExoPlayerPool
|
||||
fun provideAndroidCallAudioManager(): AudioManagerCompat
|
||||
fun provideDonationsService(signalServiceConfiguration: SignalServiceConfiguration, groupsV2Operations: GroupsV2Operations): DonationsService
|
||||
fun provideCallLinksService(signalServiceConfiguration: SignalServiceConfiguration, groupsV2Operations: GroupsV2Operations): CallLinksService
|
||||
fun provideProfileService(profileOperations: ClientZkProfileOperations, signalServiceMessageReceiver: SignalServiceMessageReceiver, signalWebSocket: SignalWebSocket): ProfileService
|
||||
fun provideDeadlockDetector(): DeadlockDetector
|
||||
fun provideClientZkReceiptOperations(signalServiceConfiguration: SignalServiceConfiguration): ClientZkReceiptOperations
|
||||
fun provideScheduledMessageManager(): ScheduledMessageManager
|
||||
fun provideLibsignalNetwork(config: SignalServiceConfiguration): LibSignalNetwork
|
||||
}
|
||||
}
|
||||
@@ -1,731 +0,0 @@
|
||||
package org.thoughtcrime.securesms.dependencies;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import org.signal.core.util.concurrent.DeadlockDetector;
|
||||
import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
|
||||
import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations;
|
||||
import org.thoughtcrime.securesms.components.TypingStatusRepository;
|
||||
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl;
|
||||
import org.thoughtcrime.securesms.database.DatabaseObserver;
|
||||
import org.thoughtcrime.securesms.database.PendingRetryReceiptCache;
|
||||
import org.thoughtcrime.securesms.groups.GroupsV2Authorization;
|
||||
import org.thoughtcrime.securesms.groups.GroupsV2AuthorizationMemoryValueCache;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
|
||||
import org.thoughtcrime.securesms.messages.IncomingMessageObserver;
|
||||
import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.payments.Payments;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceTrustStore;
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
|
||||
import org.thoughtcrime.securesms.revealable.ViewOnceMessageManager;
|
||||
import org.thoughtcrime.securesms.service.DeletedCallEventManager;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.service.ExpiringStoriesManager;
|
||||
import org.thoughtcrime.securesms.service.PendingRetryReceiptManager;
|
||||
import org.thoughtcrime.securesms.service.ScheduledMessageManager;
|
||||
import org.thoughtcrime.securesms.service.TrimThreadsByDateManager;
|
||||
import org.thoughtcrime.securesms.service.webrtc.SignalCallManager;
|
||||
import org.thoughtcrime.securesms.shakereport.ShakeToReport;
|
||||
import org.thoughtcrime.securesms.util.AppForegroundObserver;
|
||||
import org.thoughtcrime.securesms.util.EarlyMessageCache;
|
||||
import org.thoughtcrime.securesms.util.FrameRateTracker;
|
||||
import org.thoughtcrime.securesms.video.exo.ExoPlayerPool;
|
||||
import org.thoughtcrime.securesms.video.exo.GiphyMp4Cache;
|
||||
import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool;
|
||||
import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.SignalServiceDataStore;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||
import org.whispersystems.signalservice.api.services.CallLinksService;
|
||||
import org.whispersystems.signalservice.api.services.DonationsService;
|
||||
import org.whispersystems.signalservice.api.services.ProfileService;
|
||||
import org.whispersystems.signalservice.api.util.Tls12SocketFactory;
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||
import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
import org.whispersystems.signalservice.internal.websocket.LibSignalNetwork;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
* Location for storing and retrieving application-scoped singletons. Users must call
|
||||
* {@link #init(Application, Provider)} before using any of the methods, preferably early on in
|
||||
* {@link Application#onCreate()}.
|
||||
*
|
||||
* All future application-scoped singletons should be written as normal objects, then placed here
|
||||
* to manage their singleton-ness.
|
||||
*/
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public class ApplicationDependencies {
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
private static final Object FRAME_RATE_TRACKER_LOCK = new Object();
|
||||
private static final Object JOB_MANAGER_LOCK = new Object();
|
||||
private static final Object SIGNAL_HTTP_CLIENT_LOCK = new Object();
|
||||
private static final Object LIBSIGNAL_NETWORK_LOCK = new Object();
|
||||
|
||||
private static Application application;
|
||||
private static Provider provider;
|
||||
private static AppForegroundObserver appForegroundObserver;
|
||||
|
||||
private static volatile SignalServiceAccountManager accountManager;
|
||||
private static volatile SignalServiceMessageSender messageSender;
|
||||
private static volatile SignalServiceMessageReceiver messageReceiver;
|
||||
private static volatile IncomingMessageObserver incomingMessageObserver;
|
||||
private static volatile LiveRecipientCache recipientCache;
|
||||
private static volatile JobManager jobManager;
|
||||
private static volatile FrameRateTracker frameRateTracker;
|
||||
private static volatile MegaphoneRepository megaphoneRepository;
|
||||
private static volatile GroupsV2Authorization groupsV2Authorization;
|
||||
private static volatile GroupsV2Operations groupsV2Operations;
|
||||
private static volatile EarlyMessageCache earlyMessageCache;
|
||||
private static volatile TypingStatusRepository typingStatusRepository;
|
||||
private static volatile TypingStatusSender typingStatusSender;
|
||||
private static volatile DatabaseObserver databaseObserver;
|
||||
private static volatile TrimThreadsByDateManager trimThreadsByDateManager;
|
||||
private static volatile ViewOnceMessageManager viewOnceMessageManager;
|
||||
private static volatile ExpiringStoriesManager expiringStoriesManager;
|
||||
private static volatile ExpiringMessageManager expiringMessageManager;
|
||||
private static volatile DeletedCallEventManager deletedCallEventManager;
|
||||
private static volatile Payments payments;
|
||||
private static volatile SignalCallManager signalCallManager;
|
||||
private static volatile ShakeToReport shakeToReport;
|
||||
private static volatile OkHttpClient okHttpClient;
|
||||
private static volatile OkHttpClient signalOkHttpClient;
|
||||
private static volatile PendingRetryReceiptManager pendingRetryReceiptManager;
|
||||
private static volatile PendingRetryReceiptCache pendingRetryReceiptCache;
|
||||
private static volatile SignalWebSocket signalWebSocket;
|
||||
private static volatile MessageNotifier messageNotifier;
|
||||
private static volatile SignalServiceDataStoreImpl protocolStore;
|
||||
private static volatile GiphyMp4Cache giphyMp4Cache;
|
||||
private static volatile SimpleExoPlayerPool exoPlayerPool;
|
||||
private static volatile AudioManagerCompat audioManagerCompat;
|
||||
private static volatile DonationsService donationsService;
|
||||
private static volatile CallLinksService callLinksService;
|
||||
private static volatile ProfileService profileService;
|
||||
private static volatile DeadlockDetector deadlockDetector;
|
||||
private static volatile ClientZkReceiptOperations clientZkReceiptOperations;
|
||||
private static volatile ScheduledMessageManager scheduledMessagesManager;
|
||||
private static volatile LibSignalNetwork libsignalNetwork;
|
||||
|
||||
@MainThread
|
||||
public static void init(@NonNull Application application, @NonNull Provider provider) {
|
||||
synchronized (LOCK) {
|
||||
if (ApplicationDependencies.application != null || ApplicationDependencies.provider != null) {
|
||||
throw new IllegalStateException("Already initialized!");
|
||||
}
|
||||
|
||||
ApplicationDependencies.application = application;
|
||||
ApplicationDependencies.provider = provider;
|
||||
ApplicationDependencies.appForegroundObserver = provider.provideAppForegroundObserver();
|
||||
|
||||
ApplicationDependencies.appForegroundObserver.begin();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static boolean isInitialized() {
|
||||
return ApplicationDependencies.application != null;
|
||||
}
|
||||
|
||||
public static @NonNull Application getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
public static @NonNull SignalServiceAccountManager getSignalServiceAccountManager() {
|
||||
SignalServiceAccountManager local = accountManager;
|
||||
|
||||
if (local != null) {
|
||||
return local;
|
||||
}
|
||||
|
||||
synchronized (LOCK) {
|
||||
if (accountManager == null) {
|
||||
accountManager = provider.provideSignalServiceAccountManager(getSignalServiceNetworkAccess().getConfiguration(), getGroupsV2Operations());
|
||||
}
|
||||
return accountManager;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull GroupsV2Authorization getGroupsV2Authorization() {
|
||||
if (groupsV2Authorization == null) {
|
||||
synchronized (LOCK) {
|
||||
if (groupsV2Authorization == null) {
|
||||
GroupsV2Authorization.ValueCache authCache = new GroupsV2AuthorizationMemoryValueCache(SignalStore.groupsV2AciAuthorizationCache());
|
||||
|
||||
groupsV2Authorization = new GroupsV2Authorization(getSignalServiceAccountManager().getGroupsV2Api(), authCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return groupsV2Authorization;
|
||||
}
|
||||
|
||||
public static @NonNull GroupsV2Operations getGroupsV2Operations() {
|
||||
if (groupsV2Operations == null) {
|
||||
synchronized (LOCK) {
|
||||
if (groupsV2Operations == null) {
|
||||
groupsV2Operations = provider.provideGroupsV2Operations(getSignalServiceNetworkAccess().getConfiguration());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return groupsV2Operations;
|
||||
}
|
||||
|
||||
public static @NonNull SignalServiceMessageSender getSignalServiceMessageSender() {
|
||||
SignalServiceMessageSender local = messageSender;
|
||||
|
||||
if (local != null) {
|
||||
return local;
|
||||
}
|
||||
|
||||
synchronized (LOCK) {
|
||||
if (messageSender == null) {
|
||||
messageSender = provider.provideSignalServiceMessageSender(getSignalWebSocket(), getProtocolStore(), getSignalServiceNetworkAccess().getConfiguration());
|
||||
}
|
||||
return messageSender;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull SignalServiceMessageReceiver getSignalServiceMessageReceiver() {
|
||||
synchronized (LOCK) {
|
||||
if (messageReceiver == null) {
|
||||
messageReceiver = provider.provideSignalServiceMessageReceiver(getSignalServiceNetworkAccess().getConfiguration());
|
||||
}
|
||||
return messageReceiver;
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetSignalServiceMessageReceiver() {
|
||||
synchronized (LOCK) {
|
||||
messageReceiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeConnections() {
|
||||
synchronized (LOCK) {
|
||||
if (incomingMessageObserver != null) {
|
||||
incomingMessageObserver.terminateAsync();
|
||||
}
|
||||
|
||||
if (messageSender != null) {
|
||||
messageSender.cancelInFlightRequests();
|
||||
}
|
||||
|
||||
incomingMessageObserver = null;
|
||||
messageReceiver = null;
|
||||
accountManager = null;
|
||||
messageSender = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetAllNetworkConnections() {
|
||||
synchronized (LOCK) {
|
||||
closeConnections();
|
||||
if (libsignalNetwork != null) {
|
||||
libsignalNetwork.resetSettings(getSignalServiceNetworkAccess().getConfiguration());
|
||||
}
|
||||
if (signalWebSocket != null) {
|
||||
signalWebSocket.forceNewWebSockets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull SignalServiceNetworkAccess getSignalServiceNetworkAccess() {
|
||||
return provider.provideSignalServiceNetworkAccess();
|
||||
}
|
||||
|
||||
public static @NonNull LiveRecipientCache getRecipientCache() {
|
||||
if (recipientCache == null) {
|
||||
synchronized (LOCK) {
|
||||
if (recipientCache == null) {
|
||||
recipientCache = provider.provideRecipientCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return recipientCache;
|
||||
}
|
||||
|
||||
public static @NonNull JobManager getJobManager() {
|
||||
if (jobManager == null) {
|
||||
synchronized (JOB_MANAGER_LOCK) {
|
||||
if (jobManager == null) {
|
||||
jobManager = provider.provideJobManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jobManager;
|
||||
}
|
||||
|
||||
public static @NonNull FrameRateTracker getFrameRateTracker() {
|
||||
if (frameRateTracker == null) {
|
||||
synchronized (FRAME_RATE_TRACKER_LOCK) {
|
||||
if (frameRateTracker == null) {
|
||||
frameRateTracker = provider.provideFrameRateTracker();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frameRateTracker;
|
||||
}
|
||||
|
||||
public static @NonNull MegaphoneRepository getMegaphoneRepository() {
|
||||
if (megaphoneRepository == null) {
|
||||
synchronized (LOCK) {
|
||||
if (megaphoneRepository == null) {
|
||||
megaphoneRepository = provider.provideMegaphoneRepository();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return megaphoneRepository;
|
||||
}
|
||||
|
||||
public static @NonNull EarlyMessageCache getEarlyMessageCache() {
|
||||
if (earlyMessageCache == null) {
|
||||
synchronized (LOCK) {
|
||||
if (earlyMessageCache == null) {
|
||||
earlyMessageCache = provider.provideEarlyMessageCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return earlyMessageCache;
|
||||
}
|
||||
|
||||
public static @NonNull MessageNotifier getMessageNotifier() {
|
||||
if (messageNotifier == null) {
|
||||
synchronized (LOCK) {
|
||||
if (messageNotifier == null) {
|
||||
messageNotifier = provider.provideMessageNotifier();
|
||||
}
|
||||
}
|
||||
}
|
||||
return messageNotifier;
|
||||
}
|
||||
|
||||
public static @NonNull IncomingMessageObserver getIncomingMessageObserver() {
|
||||
IncomingMessageObserver local = incomingMessageObserver;
|
||||
|
||||
if (local != null) {
|
||||
return local;
|
||||
}
|
||||
|
||||
synchronized (LOCK) {
|
||||
if (incomingMessageObserver == null) {
|
||||
incomingMessageObserver = provider.provideIncomingMessageObserver();
|
||||
}
|
||||
return incomingMessageObserver;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull TrimThreadsByDateManager getTrimThreadsByDateManager() {
|
||||
if (trimThreadsByDateManager == null) {
|
||||
synchronized (LOCK) {
|
||||
if (trimThreadsByDateManager == null) {
|
||||
trimThreadsByDateManager = provider.provideTrimThreadsByDateManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return trimThreadsByDateManager;
|
||||
}
|
||||
|
||||
public static @NonNull ViewOnceMessageManager getViewOnceMessageManager() {
|
||||
if (viewOnceMessageManager == null) {
|
||||
synchronized (LOCK) {
|
||||
if (viewOnceMessageManager == null) {
|
||||
viewOnceMessageManager = provider.provideViewOnceMessageManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return viewOnceMessageManager;
|
||||
}
|
||||
|
||||
public static @NonNull ExpiringStoriesManager getExpireStoriesManager() {
|
||||
if (expiringStoriesManager == null) {
|
||||
synchronized (LOCK) {
|
||||
if (expiringStoriesManager == null) {
|
||||
expiringStoriesManager = provider.provideExpiringStoriesManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expiringStoriesManager;
|
||||
}
|
||||
|
||||
public static @NonNull PendingRetryReceiptManager getPendingRetryReceiptManager() {
|
||||
if (pendingRetryReceiptManager == null) {
|
||||
synchronized (LOCK) {
|
||||
if (pendingRetryReceiptManager == null) {
|
||||
pendingRetryReceiptManager = provider.providePendingRetryReceiptManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pendingRetryReceiptManager;
|
||||
}
|
||||
|
||||
public static @NonNull ExpiringMessageManager getExpiringMessageManager() {
|
||||
if (expiringMessageManager == null) {
|
||||
synchronized (LOCK) {
|
||||
if (expiringMessageManager == null) {
|
||||
expiringMessageManager = provider.provideExpiringMessageManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expiringMessageManager;
|
||||
}
|
||||
|
||||
public static @NonNull DeletedCallEventManager getDeletedCallEventManager() {
|
||||
if (deletedCallEventManager == null) {
|
||||
synchronized (LOCK) {
|
||||
if (deletedCallEventManager == null) {
|
||||
deletedCallEventManager = provider.provideDeletedCallEventManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deletedCallEventManager;
|
||||
}
|
||||
|
||||
public static @NonNull ScheduledMessageManager getScheduledMessageManager() {
|
||||
if (scheduledMessagesManager == null) {
|
||||
synchronized (LOCK) {
|
||||
if (scheduledMessagesManager == null) {
|
||||
scheduledMessagesManager = provider.provideScheduledMessageManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scheduledMessagesManager;
|
||||
}
|
||||
|
||||
public static TypingStatusRepository getTypingStatusRepository() {
|
||||
if (typingStatusRepository == null) {
|
||||
synchronized (LOCK) {
|
||||
if (typingStatusRepository == null) {
|
||||
typingStatusRepository = provider.provideTypingStatusRepository();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return typingStatusRepository;
|
||||
}
|
||||
|
||||
public static TypingStatusSender getTypingStatusSender() {
|
||||
if (typingStatusSender == null) {
|
||||
synchronized (LOCK) {
|
||||
if (typingStatusSender == null) {
|
||||
typingStatusSender = provider.provideTypingStatusSender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return typingStatusSender;
|
||||
}
|
||||
|
||||
public static @NonNull DatabaseObserver getDatabaseObserver() {
|
||||
if (databaseObserver == null) {
|
||||
synchronized (LOCK) {
|
||||
if (databaseObserver == null) {
|
||||
databaseObserver = provider.provideDatabaseObserver();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return databaseObserver;
|
||||
}
|
||||
|
||||
public static @NonNull Payments getPayments() {
|
||||
if (payments == null) {
|
||||
synchronized (LOCK) {
|
||||
if (payments == null) {
|
||||
payments = provider.providePayments(getSignalServiceAccountManager());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return payments;
|
||||
}
|
||||
|
||||
public static @NonNull ShakeToReport getShakeToReport() {
|
||||
if (shakeToReport == null) {
|
||||
synchronized (LOCK) {
|
||||
if (shakeToReport == null) {
|
||||
shakeToReport = provider.provideShakeToReport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shakeToReport;
|
||||
}
|
||||
|
||||
public static @NonNull SignalCallManager getSignalCallManager() {
|
||||
if (signalCallManager == null) {
|
||||
synchronized (LOCK) {
|
||||
if (signalCallManager == null) {
|
||||
signalCallManager = provider.provideSignalCallManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return signalCallManager;
|
||||
}
|
||||
|
||||
public static @NonNull OkHttpClient getOkHttpClient() {
|
||||
if (okHttpClient == null) {
|
||||
synchronized (LOCK) {
|
||||
if (okHttpClient == null) {
|
||||
okHttpClient = new OkHttpClient.Builder()
|
||||
.addInterceptor(new StandardUserAgentInterceptor())
|
||||
.dns(SignalServiceNetworkAccess.DNS)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return okHttpClient;
|
||||
}
|
||||
|
||||
public static @NonNull OkHttpClient getSignalOkHttpClient() {
|
||||
if (signalOkHttpClient == null) {
|
||||
synchronized (SIGNAL_HTTP_CLIENT_LOCK) {
|
||||
if (signalOkHttpClient == null) {
|
||||
try {
|
||||
OkHttpClient baseClient = ApplicationDependencies.getOkHttpClient();
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
TrustStore trustStore = new SignalServiceTrustStore(ApplicationDependencies.getApplication());
|
||||
TrustManager[] trustManagers = BlacklistingTrustManager.createFor(trustStore);
|
||||
|
||||
sslContext.init(null, trustManagers, null);
|
||||
|
||||
signalOkHttpClient = baseClient.newBuilder()
|
||||
.sslSocketFactory(new Tls12SocketFactory(sslContext.getSocketFactory()), (X509TrustManager) trustManagers[0])
|
||||
.connectionSpecs(Util.immutableList(ConnectionSpec.RESTRICTED_TLS))
|
||||
.build();
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return signalOkHttpClient;
|
||||
}
|
||||
|
||||
public static @NonNull AppForegroundObserver getAppForegroundObserver() {
|
||||
return appForegroundObserver;
|
||||
}
|
||||
|
||||
public static @NonNull PendingRetryReceiptCache getPendingRetryReceiptCache() {
|
||||
if (pendingRetryReceiptCache == null) {
|
||||
synchronized (LOCK) {
|
||||
if (pendingRetryReceiptCache == null) {
|
||||
pendingRetryReceiptCache = provider.providePendingRetryReceiptCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pendingRetryReceiptCache;
|
||||
}
|
||||
|
||||
public static @NonNull SignalWebSocket getSignalWebSocket() {
|
||||
if (signalWebSocket == null) {
|
||||
synchronized (LOCK) {
|
||||
if (signalWebSocket == null) {
|
||||
signalWebSocket = provider.provideSignalWebSocket(() -> getSignalServiceNetworkAccess().getConfiguration(), ApplicationDependencies::getLibsignalNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
return signalWebSocket;
|
||||
}
|
||||
|
||||
public static @NonNull SignalServiceDataStoreImpl getProtocolStore() {
|
||||
if (protocolStore == null) {
|
||||
synchronized (LOCK) {
|
||||
if (protocolStore == null) {
|
||||
protocolStore = provider.provideProtocolStore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return protocolStore;
|
||||
}
|
||||
|
||||
public static void resetProtocolStores() {
|
||||
synchronized (LOCK) {
|
||||
protocolStore = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull GiphyMp4Cache getGiphyMp4Cache() {
|
||||
if (giphyMp4Cache == null) {
|
||||
synchronized (LOCK) {
|
||||
if (giphyMp4Cache == null) {
|
||||
giphyMp4Cache = provider.provideGiphyMp4Cache();
|
||||
}
|
||||
}
|
||||
}
|
||||
return giphyMp4Cache;
|
||||
}
|
||||
|
||||
public static @NonNull ExoPlayerPool getExoPlayerPool() {
|
||||
if (exoPlayerPool == null) {
|
||||
synchronized (LOCK) {
|
||||
if (exoPlayerPool == null) {
|
||||
exoPlayerPool = provider.provideExoPlayerPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
return exoPlayerPool;
|
||||
}
|
||||
|
||||
public static @NonNull AudioManagerCompat getAndroidCallAudioManager() {
|
||||
if (audioManagerCompat == null) {
|
||||
synchronized (LOCK) {
|
||||
if (audioManagerCompat == null) {
|
||||
audioManagerCompat = provider.provideAndroidCallAudioManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return audioManagerCompat;
|
||||
}
|
||||
|
||||
public static @NonNull DonationsService getDonationsService() {
|
||||
if (donationsService == null) {
|
||||
synchronized (LOCK) {
|
||||
if (donationsService == null) {
|
||||
donationsService = provider.provideDonationsService(getSignalServiceNetworkAccess().getConfiguration(), getGroupsV2Operations());
|
||||
}
|
||||
}
|
||||
}
|
||||
return donationsService;
|
||||
}
|
||||
|
||||
public static @NonNull CallLinksService getCallLinksService() {
|
||||
if (callLinksService == null) {
|
||||
synchronized (LOCK) {
|
||||
if (callLinksService == null) {
|
||||
callLinksService = provider.provideCallLinksService(getSignalServiceNetworkAccess().getConfiguration(), getGroupsV2Operations());
|
||||
}
|
||||
}
|
||||
}
|
||||
return callLinksService;
|
||||
}
|
||||
|
||||
public static @NonNull ProfileService getProfileService() {
|
||||
if (profileService == null) {
|
||||
synchronized (LOCK) {
|
||||
if (profileService == null) {
|
||||
profileService = provider.provideProfileService(ApplicationDependencies.getGroupsV2Operations().getProfileOperations(),
|
||||
ApplicationDependencies.getSignalServiceMessageReceiver(),
|
||||
ApplicationDependencies.getSignalWebSocket());
|
||||
}
|
||||
}
|
||||
}
|
||||
return profileService;
|
||||
}
|
||||
|
||||
public static @NonNull ClientZkReceiptOperations getClientZkReceiptOperations() {
|
||||
if (clientZkReceiptOperations == null) {
|
||||
synchronized (LOCK) {
|
||||
if (clientZkReceiptOperations == null) {
|
||||
clientZkReceiptOperations = provider.provideClientZkReceiptOperations(getSignalServiceNetworkAccess().getConfiguration());
|
||||
}
|
||||
}
|
||||
}
|
||||
return clientZkReceiptOperations;
|
||||
}
|
||||
|
||||
public static @NonNull DeadlockDetector getDeadlockDetector() {
|
||||
if (deadlockDetector == null) {
|
||||
synchronized (LOCK) {
|
||||
if (deadlockDetector == null) {
|
||||
deadlockDetector = provider.provideDeadlockDetector();
|
||||
}
|
||||
}
|
||||
}
|
||||
return deadlockDetector;
|
||||
}
|
||||
|
||||
public static @NonNull LibSignalNetwork getLibsignalNetwork() {
|
||||
if (libsignalNetwork == null) {
|
||||
synchronized (LIBSIGNAL_NETWORK_LOCK) {
|
||||
if (libsignalNetwork == null) {
|
||||
libsignalNetwork = provider.provideLibsignalNetwork(getSignalServiceNetworkAccess().getConfiguration());
|
||||
}
|
||||
}
|
||||
}
|
||||
return libsignalNetwork;
|
||||
}
|
||||
|
||||
public interface Provider {
|
||||
@NonNull GroupsV2Operations provideGroupsV2Operations(@NonNull SignalServiceConfiguration signalServiceConfiguration);
|
||||
@NonNull SignalServiceAccountManager provideSignalServiceAccountManager(@NonNull SignalServiceConfiguration signalServiceConfiguration, @NonNull GroupsV2Operations groupsV2Operations);
|
||||
@NonNull SignalServiceMessageSender provideSignalServiceMessageSender(@NonNull SignalWebSocket signalWebSocket, @NonNull SignalServiceDataStore protocolStore, @NonNull SignalServiceConfiguration signalServiceConfiguration);
|
||||
@NonNull SignalServiceMessageReceiver provideSignalServiceMessageReceiver(@NonNull SignalServiceConfiguration signalServiceConfiguration);
|
||||
@NonNull SignalServiceNetworkAccess provideSignalServiceNetworkAccess();
|
||||
@NonNull LiveRecipientCache provideRecipientCache();
|
||||
@NonNull JobManager provideJobManager();
|
||||
@NonNull FrameRateTracker provideFrameRateTracker();
|
||||
@NonNull MegaphoneRepository provideMegaphoneRepository();
|
||||
@NonNull EarlyMessageCache provideEarlyMessageCache();
|
||||
@NonNull MessageNotifier provideMessageNotifier();
|
||||
@NonNull IncomingMessageObserver provideIncomingMessageObserver();
|
||||
@NonNull TrimThreadsByDateManager provideTrimThreadsByDateManager();
|
||||
@NonNull ViewOnceMessageManager provideViewOnceMessageManager();
|
||||
@NonNull ExpiringStoriesManager provideExpiringStoriesManager();
|
||||
@NonNull ExpiringMessageManager provideExpiringMessageManager();
|
||||
@NonNull DeletedCallEventManager provideDeletedCallEventManager();
|
||||
@NonNull TypingStatusRepository provideTypingStatusRepository();
|
||||
@NonNull TypingStatusSender provideTypingStatusSender();
|
||||
@NonNull DatabaseObserver provideDatabaseObserver();
|
||||
@NonNull Payments providePayments(@NonNull SignalServiceAccountManager signalServiceAccountManager);
|
||||
@NonNull ShakeToReport provideShakeToReport();
|
||||
@NonNull AppForegroundObserver provideAppForegroundObserver();
|
||||
@NonNull SignalCallManager provideSignalCallManager();
|
||||
@NonNull PendingRetryReceiptManager providePendingRetryReceiptManager();
|
||||
@NonNull PendingRetryReceiptCache providePendingRetryReceiptCache();
|
||||
@NonNull SignalWebSocket provideSignalWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull Supplier<LibSignalNetwork> libSignalNetworkSupplier);
|
||||
@NonNull SignalServiceDataStoreImpl provideProtocolStore();
|
||||
@NonNull GiphyMp4Cache provideGiphyMp4Cache();
|
||||
@NonNull SimpleExoPlayerPool provideExoPlayerPool();
|
||||
@NonNull AudioManagerCompat provideAndroidCallAudioManager();
|
||||
@NonNull DonationsService provideDonationsService(@NonNull SignalServiceConfiguration signalServiceConfiguration, @NonNull GroupsV2Operations groupsV2Operations);
|
||||
@NonNull CallLinksService provideCallLinksService(@NonNull SignalServiceConfiguration signalServiceConfiguration, @NonNull GroupsV2Operations groupsV2Operations);
|
||||
@NonNull ProfileService provideProfileService(@NonNull ClientZkProfileOperations profileOperations, @NonNull SignalServiceMessageReceiver signalServiceMessageReceiver, @NonNull SignalWebSocket signalWebSocket);
|
||||
@NonNull DeadlockDetector provideDeadlockDetector();
|
||||
@NonNull ClientZkReceiptOperations provideClientZkReceiptOperations(@NonNull SignalServiceConfiguration signalServiceConfiguration);
|
||||
@NonNull ScheduledMessageManager provideScheduledMessageManager();
|
||||
@NonNull LibSignalNetwork provideLibsignalNetwork(@NonNull SignalServiceConfiguration config);
|
||||
}
|
||||
}
|
||||
@@ -104,9 +104,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ApplicationDependencies.Provider} that provides real app dependencies.
|
||||
* Implementation of {@link AppDependencies.Provider} that provides real app dependencies.
|
||||
*/
|
||||
public class ApplicationDependencyProvider implements ApplicationDependencies.Provider {
|
||||
public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
|
||||
private final Application context;
|
||||
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.dependencies
|
||||
|
||||
import android.app.Application
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import io.reactivex.rxjava3.subjects.Subject
|
||||
import okhttp3.ConnectionSpec
|
||||
import okhttp3.OkHttpClient
|
||||
import org.signal.core.util.resettableLazy
|
||||
import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl
|
||||
import org.thoughtcrime.securesms.groups.GroupsV2Authorization
|
||||
import org.thoughtcrime.securesms.groups.GroupsV2AuthorizationMemoryValueCache
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.messages.IncomingMessageObserver
|
||||
import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor
|
||||
import org.thoughtcrime.securesms.payments.Payments
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess
|
||||
import org.thoughtcrime.securesms.push.SignalServiceTrustStore
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
||||
import org.whispersystems.signalservice.api.SignalWebSocket
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
|
||||
import org.whispersystems.signalservice.api.push.TrustStore
|
||||
import org.whispersystems.signalservice.api.services.CallLinksService
|
||||
import org.whispersystems.signalservice.api.services.DonationsService
|
||||
import org.whispersystems.signalservice.api.services.ProfileService
|
||||
import org.whispersystems.signalservice.api.util.Tls12SocketFactory
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
|
||||
import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager
|
||||
import org.whispersystems.signalservice.internal.util.Util
|
||||
import org.whispersystems.signalservice.internal.websocket.LibSignalNetwork
|
||||
import java.security.KeyManagementException
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
/**
|
||||
* A subset of [AppDependencies] that relies on the network. We bundle them together because when the network
|
||||
* needs to get reset, we just throw out the whole thing and recreate it.
|
||||
*/
|
||||
class NetworkDependenciesModule(
|
||||
private val application: Application,
|
||||
private val provider: AppDependencies.Provider,
|
||||
private val webSocketStateSubject: Subject<WebSocketConnectionState>
|
||||
) {
|
||||
|
||||
private val disposables: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
val signalServiceNetworkAccess: SignalServiceNetworkAccess by lazy {
|
||||
provider.provideSignalServiceNetworkAccess()
|
||||
}
|
||||
|
||||
private val _protocolStore = resettableLazy {
|
||||
provider.provideProtocolStore()
|
||||
}
|
||||
val protocolStore: SignalServiceDataStoreImpl by _protocolStore
|
||||
|
||||
private val _signalServiceMessageSender = resettableLazy {
|
||||
provider.provideSignalServiceMessageSender(signalWebSocket, protocolStore, signalServiceNetworkAccess.getConfiguration())
|
||||
}
|
||||
val signalServiceMessageSender: SignalServiceMessageSender by _signalServiceMessageSender
|
||||
|
||||
val incomingMessageObserver: IncomingMessageObserver by lazy {
|
||||
provider.provideIncomingMessageObserver()
|
||||
}
|
||||
|
||||
val signalServiceAccountManager: SignalServiceAccountManager by lazy {
|
||||
provider.provideSignalServiceAccountManager(signalServiceNetworkAccess.getConfiguration(), groupsV2Operations)
|
||||
}
|
||||
|
||||
val libsignalNetwork: LibSignalNetwork by lazy {
|
||||
provider.provideLibsignalNetwork(signalServiceNetworkAccess.getConfiguration())
|
||||
}
|
||||
|
||||
val signalWebSocket: SignalWebSocket by lazy {
|
||||
provider.provideSignalWebSocket({ signalServiceNetworkAccess.getConfiguration() }, { libsignalNetwork }).also {
|
||||
disposables += it.webSocketState.subscribe { webSocketStateSubject.onNext(it) }
|
||||
}
|
||||
}
|
||||
|
||||
val groupsV2Authorization: GroupsV2Authorization by lazy {
|
||||
val authCache: GroupsV2Authorization.ValueCache = GroupsV2AuthorizationMemoryValueCache(SignalStore.groupsV2AciAuthorizationCache())
|
||||
GroupsV2Authorization(signalServiceAccountManager.groupsV2Api, authCache)
|
||||
}
|
||||
|
||||
val groupsV2Operations: GroupsV2Operations by lazy {
|
||||
provider.provideGroupsV2Operations(signalServiceNetworkAccess.getConfiguration())
|
||||
}
|
||||
|
||||
val clientZkReceiptOperations: ClientZkReceiptOperations by lazy {
|
||||
provider.provideClientZkReceiptOperations(signalServiceNetworkAccess.getConfiguration())
|
||||
}
|
||||
|
||||
val signalServiceMessageReceiver: SignalServiceMessageReceiver by lazy {
|
||||
provider.provideSignalServiceMessageReceiver(signalServiceNetworkAccess.getConfiguration())
|
||||
}
|
||||
|
||||
val payments: Payments by lazy {
|
||||
provider.providePayments(signalServiceAccountManager)
|
||||
}
|
||||
|
||||
val callLinksService: CallLinksService by lazy {
|
||||
provider.provideCallLinksService(signalServiceNetworkAccess.getConfiguration(), groupsV2Operations)
|
||||
}
|
||||
|
||||
val profileService: ProfileService by lazy {
|
||||
provider.provideProfileService(groupsV2Operations.profileOperations, signalServiceMessageReceiver, signalWebSocket)
|
||||
}
|
||||
|
||||
val donationsService: DonationsService by lazy {
|
||||
provider.provideDonationsService(signalServiceNetworkAccess.getConfiguration(), groupsV2Operations)
|
||||
}
|
||||
|
||||
val okHttpClient: OkHttpClient by lazy {
|
||||
OkHttpClient.Builder()
|
||||
.addInterceptor(StandardUserAgentInterceptor())
|
||||
.dns(SignalServiceNetworkAccess.DNS)
|
||||
.build()
|
||||
}
|
||||
|
||||
val signalOkHttpClient: OkHttpClient by lazy {
|
||||
try {
|
||||
val baseClient = okHttpClient
|
||||
val sslContext = SSLContext.getInstance("TLS")
|
||||
val trustStore: TrustStore = SignalServiceTrustStore(application)
|
||||
val trustManagers = BlacklistingTrustManager.createFor(trustStore)
|
||||
|
||||
sslContext.init(null, trustManagers, null)
|
||||
|
||||
baseClient.newBuilder()
|
||||
.sslSocketFactory(Tls12SocketFactory(sslContext.socketFactory), trustManagers[0] as X509TrustManager)
|
||||
.connectionSpecs(Util.immutableList(ConnectionSpec.RESTRICTED_TLS))
|
||||
.build()
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
throw AssertionError(e)
|
||||
} catch (e: KeyManagementException) {
|
||||
throw AssertionError(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun closeConnections() {
|
||||
incomingMessageObserver.terminateAsync()
|
||||
if (_signalServiceMessageSender.isInitialized()) {
|
||||
signalServiceMessageSender.cancelInFlightRequests()
|
||||
}
|
||||
disposables.clear()
|
||||
}
|
||||
|
||||
fun resetProtocolStores() {
|
||||
_protocolStore.reset()
|
||||
_signalServiceMessageSender.reset()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user