session-android/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java

556 lines
22 KiB
Java
Raw Normal View History

/*
* Copyright (C) 2013 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import android.content.Context;
2019-11-21 05:31:01 +00:00
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
2019-11-21 05:31:01 +00:00
import android.os.Handler;
2020-09-16 03:42:18 +00:00
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
2020-09-16 03:42:18 +00:00
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner;
import androidx.multidex.MultiDexApplication;
import com.google.firebase.iid.FirebaseInstanceId;
import org.conscrypt.Conscrypt;
2021-01-21 06:04:56 +00:00
import org.session.libsession.messaging.MessagingConfiguration;
2021-02-02 04:40:43 +00:00
import org.session.libsession.messaging.avatars.AvatarHelper;
2021-03-02 01:24:09 +00:00
import org.session.libsession.snode.SnodeConfiguration;
2021-01-13 06:11:30 +00:00
import org.session.libsession.utilities.SSKEnvironment;
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
2021-01-15 05:51:53 +00:00
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
2021-01-21 05:01:10 +00:00
import org.session.libsession.utilities.dynamiclanguage.LocaleParser;
import org.signal.aesgcmprovider.AesGcmProvider;
2021-01-21 06:04:56 +00:00
import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl;
2021-01-13 06:11:30 +00:00
import org.thoughtcrime.securesms.sskenvironment.ProfileManager;
import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager;
import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository;
2018-10-29 22:14:31 +00:00
import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.session.libsession.utilities.preferences.ProfileKeyUtil;
2021-01-13 06:11:30 +00:00
import org.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
2020-10-19 04:21:15 +00:00
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
2019-03-28 15:56:35 +00:00
import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
import org.thoughtcrime.securesms.jobmanager.JobManager;
2019-03-28 15:56:35 +00:00
import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
import org.thoughtcrime.securesms.jobs.FastJobStorage;
import org.thoughtcrime.securesms.jobs.JobManagerFactories;
2019-07-01 06:49:42 +00:00
import org.thoughtcrime.securesms.jobs.PushContentReceiveJob;
import org.thoughtcrime.securesms.logging.AndroidLogger;
2021-02-03 01:22:40 +00:00
import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.logging.PersistentLogger;
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
2020-05-11 06:19:26 +00:00
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker;
import org.thoughtcrime.securesms.loki.api.ClosedGroupPoller;
2020-05-13 23:35:34 +00:00
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
2020-07-15 05:14:37 +00:00
import org.thoughtcrime.securesms.loki.api.PublicChatManager;
2020-05-11 06:19:26 +00:00
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
2020-05-13 23:35:34 +00:00
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
2020-05-11 06:19:26 +00:00
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
2021-02-05 05:35:15 +00:00
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
2020-05-11 06:19:26 +00:00
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
2020-08-27 04:38:25 +00:00
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.LocalBackupListener;
import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
2021-01-21 05:01:10 +00:00
import org.thoughtcrime.securesms.util.dynamiclanguage.LocaleParseHelper;
import org.webrtc.PeerConnectionFactory;
2017-12-22 00:37:07 +00:00
import org.webrtc.PeerConnectionFactory.InitializationOptions;
import org.webrtc.voiceengine.WebRtcAudioManager;
import org.webrtc.voiceengine.WebRtcAudioUtils;
import org.session.libsignal.service.api.messages.SignalServiceEnvelope;
import org.session.libsignal.service.api.util.StreamDetails;
import org.session.libsignal.service.internal.push.SignalServiceProtos;
import org.session.libsignal.service.loki.api.Poller;
import org.session.libsignal.service.loki.api.PushNotificationAPI;
import org.session.libsignal.service.loki.api.SnodeAPI;
import org.session.libsignal.service.loki.api.SwarmAPI;
import org.session.libsignal.service.loki.api.fileserver.FileServerAPI;
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
2021-02-19 00:03:58 +00:00
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
2020-02-24 03:57:51 +00:00
import java.io.File;
import java.io.FileInputStream;
import java.security.SecureRandom;
import java.security.Security;
2020-02-24 03:57:51 +00:00
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import dagger.ObjectGraph;
2019-06-25 03:51:24 +00:00
import kotlin.Unit;
2019-07-24 02:30:23 +00:00
import network.loki.messenger.BuildConfig;
2019-09-19 05:00:52 +00:00
import static nl.komponents.kovenant.android.KovenantAndroid.startKovenant;
import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
/**
* Will be called once when the TextSecure process is created.
*
* We're using this as an insertion point to patch up the Android PRNG disaster,
* to initialize the job manager, and to check for GCM registration freshness.
*
* @author Moxie Marlinspike
*/
2021-02-22 00:29:22 +00:00
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver {
2021-02-22 03:58:06 +00:00
public static final String PREFERENCES_NAME = "SecureSMS-Preferences";
private static final String TAG = ApplicationContext.class.getSimpleName();
private ExpiringMessageManager expiringMessageManager;
2018-10-29 22:14:31 +00:00
private TypingStatusRepository typingStatusRepository;
private TypingStatusSender typingStatusSender;
private JobManager jobManager;
2021-01-13 06:11:30 +00:00
private ReadReceiptManager readReceiptManager;
private ProfileManager profileManager;
private ObjectGraph objectGraph;
private PersistentLogger persistentLogger;
2019-06-28 06:08:27 +00:00
// Loki
public MessageNotifier messageNotifier = null;
2020-07-15 22:55:29 +00:00
public Poller poller = null;
public ClosedGroupPoller closedGroupPoller = null;
2020-07-15 04:26:20 +00:00
public PublicChatManager publicChatManager = null;
2020-07-15 02:24:43 +00:00
private PublicChatAPI publicChatAPI = null;
2020-01-16 03:35:51 +00:00
public Broadcaster broadcaster = null;
2019-06-28 06:08:27 +00:00
public SignalCommunicationModule communicationModule;
2019-06-18 02:49:21 +00:00
private volatile boolean isAppVisible;
public static ApplicationContext getInstance(Context context) {
return (ApplicationContext)context.getApplicationContext();
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate()");
2019-11-21 05:31:01 +00:00
startKovenant();
initializeSecurityProvider();
initializeLogging();
initializeCrashHandling();
initializeDependencyInjection();
NotificationChannels.create(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
2020-05-13 23:35:34 +00:00
// Loki
2020-05-25 23:03:41 +00:00
// ========
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
2020-05-13 23:35:34 +00:00
broadcaster = new Broadcaster(this);
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
2021-01-21 06:04:56 +00:00
MessagingConfiguration.Companion.configure(this,
DatabaseFactory.getStorage(this),
DatabaseFactory.getAttachmentProvider(this),
new SessionProtocolImpl(this));
2021-03-02 01:24:09 +00:00
SnodeConfiguration.Companion.configure(apiDB, broadcaster);
2020-05-13 23:35:34 +00:00
if (userPublicKey != null) {
2020-07-08 07:05:26 +00:00
SwarmAPI.Companion.configureIfNeeded(apiDB);
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
2020-05-13 23:35:34 +00:00
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
}
2020-09-21 01:17:39 +00:00
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
2021-02-17 01:27:00 +00:00
setUpStorageAPIIfNeeded();
2020-02-24 03:57:51 +00:00
resubmitProfilePictureIfNeeded();
2020-07-15 04:26:20 +00:00
publicChatManager = new PublicChatManager(this);
2020-05-13 23:35:34 +00:00
updateOpenGroupProfilePicturesIfNeeded();
2020-09-23 23:43:18 +00:00
if (userPublicKey != null) {
registerForFCMIfNeeded(false);
}
2020-08-27 04:38:25 +00:00
// Set application UI mode (day/night theme) to the user selected one.
UiModeUtilities.setupUiModeToUserSelected(this);
2020-05-25 23:03:41 +00:00
// ========
initializeJobManager();
initializeExpiringMessageManager();
initializeTypingStatusRepository();
initializeTypingStatusSender();
2021-01-13 06:11:30 +00:00
initializeReadReceiptManager();
initializeProfileManager();
2020-05-25 23:03:41 +00:00
initializePeriodicTasks();
initializeWebRtc();
initializeBlobProvider();
2021-01-13 06:11:30 +00:00
SSKEnvironment.Companion.configure(getTypingStatusRepository(), getReadReceiptManager(), getProfileManager(), messageNotifier, getExpiringMessageManager());
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
isAppVisible = true;
Log.i(TAG, "App is now visible.");
KeyCachingService.onAppForegrounded(this);
2020-05-13 23:35:34 +00:00
// Loki
2020-07-15 22:55:29 +00:00
if (poller != null) { poller.setCaughtUp(false); }
2020-03-24 02:48:23 +00:00
startPollingIfNeeded();
2020-07-15 04:26:20 +00:00
publicChatManager.markAllAsNotCaughtUp();
publicChatManager.startPollersIfNeeded();
2021-02-05 05:35:15 +00:00
MultiDeviceProtocol.syncConfigurationIfNeeded(this);
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
isAppVisible = false;
Log.i(TAG, "App is no longer visible.");
KeyCachingService.onAppBackgrounded(this);
messageNotifier.setVisibleThread(-1);
2020-05-13 23:35:34 +00:00
// Loki
2020-07-15 22:55:29 +00:00
if (poller != null) { poller.stopIfNeeded(); }
2020-09-16 04:38:40 +00:00
if (closedGroupPoller != null) { closedGroupPoller.stopIfNeeded(); }
2020-07-15 04:26:20 +00:00
if (publicChatManager != null) { publicChatManager.stopPollers(); }
}
2019-09-19 05:00:52 +00:00
@Override
public void onTerminate() {
2020-05-13 23:35:34 +00:00
stopKovenant(); // Loki
2019-09-19 05:00:52 +00:00
super.onTerminate();
}
@Override
public void injectDependencies(Object object) {
if (object instanceof InjectableType) {
objectGraph.inject(object);
}
}
2021-01-21 05:01:10 +00:00
public void initializeLocaleParser() {
LocaleParser.Companion.configure(new LocaleParseHelper());
}
public JobManager getJobManager() {
return jobManager;
}
public ExpiringMessageManager getExpiringMessageManager() {
return expiringMessageManager;
}
2018-10-29 22:14:31 +00:00
public TypingStatusRepository getTypingStatusRepository() {
return typingStatusRepository;
}
public TypingStatusSender getTypingStatusSender() {
return typingStatusSender;
}
2021-01-13 06:11:30 +00:00
public ReadReceiptManager getReadReceiptManager() { return readReceiptManager; }
public ProfileManager getProfileManager() { return profileManager; }
public boolean isAppVisible() {
return isAppVisible;
}
public PersistentLogger getPersistentLogger() {
return persistentLogger;
}
2020-05-13 23:35:34 +00:00
// Loki
2020-07-15 02:24:43 +00:00
public @Nullable PublicChatAPI getPublicChatAPI() {
if (publicChatAPI != null || !IdentityKeyUtil.hasIdentityKey(this)) { return publicChatAPI; }
2020-05-13 23:35:34 +00:00
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
2020-07-15 02:24:43 +00:00
if (userPublicKey== null) { return publicChatAPI; }
2020-05-13 23:35:34 +00:00
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
2020-10-19 04:21:15 +00:00
GroupDatabase groupDB = DatabaseFactory.getGroupDatabase(this);
publicChatAPI = new PublicChatAPI(userPublicKey, userPrivateKey, apiDB, userDB, groupDB);
2020-07-15 02:24:43 +00:00
return publicChatAPI;
}
private void initializeSecurityProvider() {
try {
Class.forName("org.signal.aesgcmprovider.AesGcmCipher");
} catch (ClassNotFoundException e) {
Log.e(TAG, "Failed to find AesGcmCipher class");
throw new ProviderInitializationException();
}
int aesPosition = Security.insertProviderAt(new AesGcmProvider(), 1);
Log.i(TAG, "Installed AesGcmProvider: " + aesPosition);
if (aesPosition < 0) {
Log.e(TAG, "Failed to install AesGcmProvider()");
throw new ProviderInitializationException();
}
int conscryptPosition = Security.insertProviderAt(Conscrypt.newProvider(), 2);
Log.i(TAG, "Installed Conscrypt provider: " + conscryptPosition);
if (conscryptPosition < 0) {
Log.w(TAG, "Did not install Conscrypt provider. May already be present.");
}
}
private void initializeLogging() {
persistentLogger = new PersistentLogger(this);
2021-02-03 01:22:40 +00:00
Log.initialize(new AndroidLogger(), persistentLogger);
}
private void initializeCrashHandling() {
final Thread.UncaughtExceptionHandler originalHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger(originalHandler));
}
private void initializeJobManager() {
2019-03-28 15:56:35 +00:00
this.jobManager = new JobManager(this, new JobManager.Configuration.Builder()
.setDataSerializer(new JsonDataSerializer())
.setJobFactories(JobManagerFactories.getJobFactories(this))
.setConstraintFactories(JobManagerFactories.getConstraintFactories(this))
.setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
.setJobStorage(new FastJobStorage(DatabaseFactory.getJobDatabase(this)))
.setDependencyInjector(this)
.build());
}
private void initializeDependencyInjection() {
2021-02-21 22:31:29 +00:00
communicationModule = new SignalCommunicationModule(this);
this.objectGraph = ObjectGraph.create(communicationModule);
}
private void initializeExpiringMessageManager() {
this.expiringMessageManager = new ExpiringMessageManager(this);
}
2018-10-29 22:14:31 +00:00
private void initializeTypingStatusRepository() {
this.typingStatusRepository = new TypingStatusRepository();
}
2021-01-13 06:11:30 +00:00
private void initializeReadReceiptManager() {
this.readReceiptManager = new ReadReceiptManager();
}
private void initializeProfileManager() {
this.profileManager = new ProfileManager();
}
2018-10-29 22:14:31 +00:00
private void initializeTypingStatusSender() {
this.typingStatusSender = new TypingStatusSender(this);
}
private void initializePeriodicTasks() {
LocalBackupListener.schedule(this);
BackgroundPollWorker.schedulePeriodic(this); // Loki
if (BuildConfig.PLAY_STORE_DISABLED) {
UpdateApkRefreshListener.schedule(this);
}
}
private void initializeWebRtc() {
try {
Set<String> HARDWARE_AEC_BLACKLIST = new HashSet<String>() {{
add("Pixel");
add("Pixel XL");
add("Moto G5");
add("Moto G (5S) Plus");
add("Moto G4");
add("TA-1053");
add("Mi A1");
add("E5823"); // Sony z5 compact
add("Redmi Note 5");
add("FP2"); // Fairphone FP2
2019-03-10 13:29:02 +00:00
add("MI 5");
}};
Set<String> OPEN_SL_ES_WHITELIST = new HashSet<String>() {{
add("Pixel");
add("Pixel XL");
}};
2017-12-22 00:37:07 +00:00
if (HARDWARE_AEC_BLACKLIST.contains(Build.MODEL)) {
WebRtcAudioUtils.setWebRtcBasedAcousticEchoCanceler(true);
}
2017-12-22 00:37:07 +00:00
if (!OPEN_SL_ES_WHITELIST.contains(Build.MODEL)) {
WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true);
}
2017-12-22 00:37:07 +00:00
2019-01-29 22:25:49 +00:00
PeerConnectionFactory.initialize(InitializationOptions.builder(this).createInitializationOptions());
} catch (UnsatisfiedLinkError e) {
Log.w(TAG, e);
}
}
private void initializeBlobProvider() {
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
BlobProvider.getInstance().onSessionStart(this);
});
}
@Override
protected void attachBaseContext(Context base) {
2021-01-21 05:01:10 +00:00
initializeLocaleParser();
super.attachBaseContext(DynamicLanguageContextWrapper.updateContext(base, TextSecurePreferences.getLanguage(base)));
}
2020-07-15 02:24:43 +00:00
private static class ProviderInitializationException extends RuntimeException { }
2019-06-07 05:21:25 +00:00
// region Loki
2019-10-24 02:35:14 +00:00
public boolean setUpStorageAPIIfNeeded() {
2020-05-13 23:35:34 +00:00
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
if (userPublicKey == null || !IdentityKeyUtil.hasIdentityKey(this)) { return false; }
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
2020-07-15 02:24:43 +00:00
FileServerAPI.Companion.configure(userPublicKey, userPrivateKey, apiDB);
2021-03-02 03:13:12 +00:00
org.session.libsession.messaging.fileserver.FileServerAPI.Companion.configure(userPublicKey, userPrivateKey, apiDB);
2020-05-13 23:35:34 +00:00
return true;
2019-09-23 01:28:17 +00:00
}
2020-04-17 03:26:11 +00:00
public void registerForFCMIfNeeded(Boolean force) {
Context context = this;
2020-04-16 06:56:12 +00:00
FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
2020-09-18 00:34:30 +00:00
Log.w("Loki", "FirebaseInstanceId.getInstance().getInstanceId() failed." + task.getException());
2020-04-16 06:56:12 +00:00
return;
}
String token = task.getResult().getToken();
2020-05-13 23:35:34 +00:00
String userPublicKey = TextSecurePreferences.getLocalNumber(context);
if (userPublicKey == null) return;
2020-04-17 02:11:27 +00:00
if (TextSecurePreferences.isUsingFCM(this)) {
2020-05-13 23:35:34 +00:00
LokiPushNotificationManager.register(token, userPublicKey, context, force);
2020-04-17 02:11:27 +00:00
} else {
LokiPushNotificationManager.unregister(token, context);
}
2020-04-16 06:56:12 +00:00
});
}
2020-03-24 02:48:23 +00:00
private void setUpPollingIfNeeded() {
2020-05-13 23:35:34 +00:00
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
if (userPublicKey == null) return;
2020-07-15 22:55:29 +00:00
if (poller != null) {
2020-07-08 07:05:26 +00:00
SnodeAPI.shared.setUserPublicKey(userPublicKey);
2020-07-15 22:55:29 +00:00
poller.setUserPublicKey(userPublicKey);
return;
}
2020-05-13 23:35:34 +00:00
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
2019-06-25 03:51:24 +00:00
Context context = this;
2020-07-08 07:05:26 +00:00
SwarmAPI.Companion.configureIfNeeded(apiDB);
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
2020-09-16 03:42:18 +00:00
poller = new Poller(userPublicKey, apiDB, envelopes -> {
for (SignalServiceProtos.Envelope envelope : envelopes) {
new PushContentReceiveJob(context).processEnvelope(new SignalServiceEnvelope(envelope), false);
2019-06-25 03:51:24 +00:00
}
2019-08-28 04:19:08 +00:00
return Unit.INSTANCE;
2019-06-25 03:51:24 +00:00
});
2021-02-18 03:14:05 +00:00
ClosedGroupPoller.Companion.configureIfNeeded(this);
closedGroupPoller = ClosedGroupPoller.Companion.getShared();
}
2019-08-05 02:08:23 +00:00
2020-03-24 02:48:23 +00:00
public void startPollingIfNeeded() {
setUpPollingIfNeeded();
2020-07-15 22:55:29 +00:00
if (poller != null) { poller.startIfNeeded(); }
if (closedGroupPoller != null) { closedGroupPoller.startIfNeeded(); }
2019-08-05 02:08:23 +00:00
}
2020-07-08 00:48:09 +00:00
public void stopPolling() {
if (poller != null) { poller.stopIfNeeded(); }
if (closedGroupPoller != null) { closedGroupPoller.stopIfNeeded(); }
2020-09-16 04:38:40 +00:00
if (publicChatManager != null) { publicChatManager.stopPollers(); }
}
2020-02-24 03:57:51 +00:00
private void resubmitProfilePictureIfNeeded() {
2020-05-13 23:35:34 +00:00
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
if (userPublicKey == null) return;
2020-02-24 03:57:51 +00:00
long now = new Date().getTime();
long lastProfilePictureUpload = TextSecurePreferences.getLastProfilePictureUpload(this);
if (now - lastProfilePictureUpload <= 14 * 24 * 60 * 60 * 1000) return;
AsyncTask.execute(() -> {
String encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this);
byte[] profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey);
try {
2021-02-17 05:09:36 +00:00
File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userPublicKey));
2020-02-24 03:57:51 +00:00
StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length());
2020-07-15 02:24:43 +00:00
FileServerAPI.shared.uploadProfilePicture(FileServerAPI.shared.getServer(), profileKey, stream, () -> {
2020-02-24 03:57:51 +00:00
TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime());
TextSecurePreferences.setProfileAvatarId(this, new SecureRandom().nextInt());
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey);
return Unit.INSTANCE;
});
} catch (Exception exception) {
// Do nothing
}
});
}
2020-05-13 23:35:34 +00:00
public void updateOpenGroupProfilePicturesIfNeeded() {
AsyncTask.execute(() -> {
2020-07-15 02:24:43 +00:00
PublicChatAPI publicChatAPI = null;
2019-12-16 10:43:08 +00:00
try {
2020-07-15 02:24:43 +00:00
publicChatAPI = getPublicChatAPI();
2019-12-16 10:43:08 +00:00
} catch (Exception e) {
// Do nothing
}
2020-05-13 23:35:34 +00:00
if (publicChatAPI == null) { return; }
byte[] profileKey = ProfileKeyUtil.getProfileKey(this);
String url = TextSecurePreferences.getProfilePictureURL(this);
Set<String> servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers();
for (String server : servers) {
if (profileKey != null) {
publicChatAPI.setProfilePicture(server, profileKey, url);
}
}
});
}
2019-11-21 22:35:15 +00:00
2021-01-13 05:13:49 +00:00
public void clearAllData(boolean isMigratingToV2KeyPair) {
String token = TextSecurePreferences.getFCMToken(this);
if (token != null && !token.isEmpty()) {
LokiPushNotificationManager.unregister(token, this);
}
2021-01-13 05:13:49 +00:00
String displayName = TextSecurePreferences.getProfileName(this);
boolean isUsingFCM = TextSecurePreferences.isUsingFCM(this);
2020-05-13 23:35:34 +00:00
TextSecurePreferences.clearAll(this);
2021-01-13 05:13:49 +00:00
if (isMigratingToV2KeyPair) {
TextSecurePreferences.setIsMigratingKeyPair(this, true);
TextSecurePreferences.setIsUsingFCM(this, isUsingFCM);
TextSecurePreferences.setProfileName(this, displayName);
}
2021-02-22 03:58:06 +00:00
getSharedPreferences(PREFERENCES_NAME, 0).edit().clear().commit();
2020-05-22 03:47:51 +00:00
if (!deleteDatabase("signal.db")) {
Log.d("Loki", "Failed to delete database.");
}
2020-05-25 00:20:18 +00:00
Util.runOnMain(() -> new Handler().postDelayed(ApplicationContext.this::restartApplication, 200));
2019-11-21 05:31:01 +00:00
}
public void restartApplication() {
2019-12-17 13:27:59 +00:00
Intent intent = new Intent(this, HomeActivity.class);
2020-05-13 23:35:34 +00:00
startActivity(Intent.makeRestartActivityTask(intent.getComponent()));
2019-11-21 05:31:01 +00:00
Runtime.getRuntime().exit(0);
}
2020-05-13 23:35:34 +00:00
2020-02-13 03:39:29 +00:00
// endregion
}