diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 678d284d4f..36c9f0787e 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -435,6 +435,7 @@ android:exported="true" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> + <!-- Loki --> <activity android:name=".loki.AccountDetailsActivity" android:launchMode="singleTask" android:theme="@style/TextSecure.LightRegistrationTheme" @@ -450,6 +451,7 @@ <activity android:name=".loki.NewConversationActivity" android:windowSoftInputMode="stateAlwaysVisible" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> + <!-- Loki --> <service android:enabled="true" android:name="org.thoughtcrime.securesms.service.WebRtcCallService"/> <service android:enabled="true" android:name=".service.ApplicationMigrationService"/> @@ -669,6 +671,14 @@ </intent-filter> </receiver> + <!-- Loki --> + <receiver android:name=".loki.BackgroundPollWorker"> + <intent-filter> + <action android:name="android.intent.action.BOOT_COMPLETED" /> + </intent-filter> + </receiver> + <!-- Loki --> + <service android:name=".jobmanager.JobSchedulerScheduler$SystemService" android:permission="android.permission.BIND_JOB_SERVICE" diff --git a/build.gradle b/build.gradle index 756aff75b2..0b72429f61 100644 --- a/build.gradle +++ b/build.gradle @@ -180,7 +180,6 @@ dependencies { implementation "com.squareup.okhttp3:okhttp:3.12.1" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "nl.komponents.kovenant:kovenant:$kovenant_version" - implementation "androidx.work:work-runtime-ktx:$work_manager_version" } android { @@ -202,7 +201,7 @@ android { multiDexEnabled true vectorDrawables.useSupportLibrary = true - project.ext.set("archivesBaseName", "Signal"); + project.ext.set("archivesBaseName", "Signal") buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L" buildConfigField "String", "SIGNAL_URL", "\"https://textsecure-service.whispersystems.org\"" diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 3f8f1fb2e9..73ca6a62d5 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -53,6 +53,7 @@ import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.PersistentLogger; import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger; +import org.thoughtcrime.securesms.loki.BackgroundPollWorker; import org.thoughtcrime.securesms.loki.LokiAPIDatabase; import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.providers.BlobProvider; @@ -152,7 +153,9 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc executePendingContactSync(); KeyCachingService.onAppForegrounded(this); // Loki - Start long polling if needed - startLongPolling(); + startLongPollingIfNeeded(); + // Loki - Stop background poll worker if needed + stopBackgroundPollingIfNeeded(); } @Override @@ -162,6 +165,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc KeyCachingService.onAppBackgrounded(this); // Loki - Stop long polling if needed if (lokiLongPoller != null) { lokiLongPoller.stopIfNeeded(); } + // Loki - Start background poll worker if needed + startBackgroundPollingIfNeeded(); } @Override @@ -284,6 +289,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc DirectoryRefreshListener.schedule(this); LocalBackupListener.schedule(this); RotateSenderCertificateListener.schedule(this); + BackgroundPollWorker.schedule(this); // Loki if (BuildConfig.PLAY_STORE_DISABLED) { UpdateApkRefreshListener.schedule(this); @@ -393,31 +399,23 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc // TODO: Implement } - public void startLongPolling() { + public void startLongPollingIfNeeded() { setUpLongPollingIfNeeded(); if (lokiLongPoller != null) { lokiLongPoller.startIfNeeded(); } } private void setUpLongPollingIfNeeded() { if (lokiLongPoller != null) return; - String hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); - if (hexEncodedPublicKey == null) return; + String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); + if (userHexEncodedPublicKey == null) return; LokiAPIDatabase database = DatabaseFactory.getLokiAPIDatabase(this); Context context = this; - lokiLongPoller = new LokiLongPoller(hexEncodedPublicKey, database, new Function1<List<SignalServiceProtos.Envelope>, Unit>() { + lokiLongPoller = new LokiLongPoller(userHexEncodedPublicKey, database, new Function1<List<SignalServiceProtos.Envelope>, Unit>() { @Override - public Unit invoke(List<SignalServiceProtos.Envelope> envelopes) { - for (SignalServiceProtos.Envelope proto : envelopes) { - SignalServiceEnvelope envelope; - if (proto.getSource() != null && proto.getSourceDevice() > 0) { - envelope = new SignalServiceEnvelope(proto.getType().getNumber(), proto.getSource(), proto.getSourceDevice(), proto.getTimestamp(), - proto.getLegacyMessage().toByteArray(), proto.getContent().toByteArray(), proto.getServerTimestamp(), proto.getServerGuid()); - } else { - envelope = new SignalServiceEnvelope(proto.getType().getNumber(), proto.getTimestamp(), proto.getLegacyMessage().toByteArray(), - proto.getContent().toByteArray(), proto.getServerTimestamp(), proto.getServerGuid()); - } - new PushContentReceiveJob(context).processEnvelope(envelope); + public Unit invoke(List<SignalServiceProtos.Envelope> protos) { + for (SignalServiceProtos.Envelope proto : protos) { + new PushContentReceiveJob(context).processEnvelope(new SignalServiceEnvelope(proto)); } return Unit.INSTANCE; } diff --git a/src/org/thoughtcrime/securesms/loki/BackgroundPollWorker.kt b/src/org/thoughtcrime/securesms/loki/BackgroundPollWorker.kt index 93f28e5301..d0ceb91125 100644 --- a/src/org/thoughtcrime/securesms/loki/BackgroundPollWorker.kt +++ b/src/org/thoughtcrime/securesms/loki/BackgroundPollWorker.kt @@ -1,20 +1,44 @@ package org.thoughtcrime.securesms.loki import android.content.Context -import androidx.work.Worker -import androidx.work.WorkerParameters +import android.content.Intent +import org.thoughtcrime.securesms.database.DatabaseFactory +import org.thoughtcrime.securesms.jobs.PushContentReceiveJob +import org.thoughtcrime.securesms.service.PersistentAlarmManagerListener +import org.thoughtcrime.securesms.util.TextSecurePreferences +import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope import org.whispersystems.signalservice.loki.api.LokiAPI -import org.whispersystems.signalservice.loki.api.LokiAPIDatabaseProtocol +import java.util.concurrent.TimeUnit -class BackgroundPollWorker(private val userHexEncodedPublicKey: String, private val apiDatabase: LokiAPIDatabaseProtocol, context: Context, parameters: WorkerParameters) : Worker(context, parameters) { +class BackgroundPollWorker : PersistentAlarmManagerListener() { - override fun doWork(): Result { - return try { - LokiAPI(userHexEncodedPublicKey, apiDatabase).getMessages().get() - // TODO: Process envelopes - Result.success() - } catch (exception: Exception) { - Result.failure() + companion object { + private val pollInterval = TimeUnit.MINUTES.toMillis(5) + + @JvmStatic + fun schedule(context: Context) { + BackgroundPollWorker().onReceive(context, Intent()) + } + } + + override fun getNextScheduledExecutionTime(context: Context): Long { + return TextSecurePreferences.getBackgroundPollTime(context) + } + + override fun onAlarm(context: Context, scheduledTime: Long): Long { + if (scheduledTime != 0L) { + val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context) + val apiDatabase = DatabaseFactory.getLokiAPIDatabase(context) + try { + LokiAPI(userHexEncodedPublicKey, apiDatabase).getMessages().get().forEach { + PushContentReceiveJob(context).processEnvelope(SignalServiceEnvelope(it)) + } + } catch (exception: Throwable) { + // Do nothing + } } + val nextTime = System.currentTimeMillis() + pollInterval + TextSecurePreferences.setBackgroundPollTime(context, nextTime) + return nextTime } -} \ No newline at end of file +} diff --git a/src/org/thoughtcrime/securesms/loki/KeyPairActivity.kt b/src/org/thoughtcrime/securesms/loki/KeyPairActivity.kt index 180ec53719..cfd62ed845 100644 --- a/src/org/thoughtcrime/securesms/loki/KeyPairActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/KeyPairActivity.kt @@ -144,7 +144,7 @@ class KeyPairActivity : BaseActionBarActivity() { TextSecurePreferences.setPromptedPushRegistration(this, true) val application = ApplicationContext.getInstance(this) application.setUpP2PAPI() - application.startLongPolling() + application.startLongPollingIfNeeded() startActivity(Intent(this, ConversationListActivity::class.java)) finish() } diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java index cd769178e4..effcc3f620 100644 --- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -1126,4 +1126,12 @@ public class TextSecurePreferences { return defaultValues; } } + + public static long getBackgroundPollTime(Context context) { + return getLongPreference(context, "background_poll_time", 0L); + } + + public static void setBackgroundPollTime(Context context, long backgroundPollTime) { + setLongPreference(context, "background_poll_time", backgroundPollTime); + } }