mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-07-03 04:25:51 +01:00
Improve cold start performance.
This commit is contained in:
committed by
Michelle Tang
parent
de2a5ea440
commit
89bffe39ae
@@ -79,6 +79,7 @@ import org.thoughtcrime.securesms.jobs.GroupV2UpdateSelfProfileKeyJob;
|
||||
import org.thoughtcrime.securesms.jobs.InAppPaymentAuthCheckJob;
|
||||
import org.thoughtcrime.securesms.jobs.InAppPaymentKeepAliveJob;
|
||||
import org.thoughtcrime.securesms.jobs.LinkedDeviceInactiveCheckJob;
|
||||
import org.thoughtcrime.securesms.jobs.MessageSendLogCleanupJob;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.PreKeysSyncJob;
|
||||
import org.thoughtcrime.securesms.jobs.ProfileUploadJob;
|
||||
@@ -229,7 +230,7 @@ public class ApplicationContext extends Application implements AppForegroundObse
|
||||
.addPostRender(RefreshSvrCredentialsJob::enqueueIfNecessary)
|
||||
.addPostRender(() -> DownloadLatestEmojiDataJob.scheduleIfNecessary(this))
|
||||
.addPostRender(EmojiSearchIndexDownloadJob::scheduleIfNecessary)
|
||||
.addPostRender(() -> SignalDatabase.messageLog().trimOldMessages(System.currentTimeMillis(), RemoteConfig.retryRespondMaxAge()))
|
||||
.addPostRender(MessageSendLogCleanupJob::enqueue)
|
||||
.addPostRender(() -> JumboEmoji.updateCurrentVersion(this))
|
||||
.addPostRender(RetrieveRemoteAnnouncementsJob::enqueue)
|
||||
.addPostRender(AndroidTelecomUtil::registerPhoneAccount)
|
||||
|
||||
@@ -1465,6 +1465,7 @@ object BackupRepository {
|
||||
}
|
||||
|
||||
SignalDatabase.remappedRecords.clearCache()
|
||||
SignalDatabase.remappedRecords.trimStaleMappings()
|
||||
AppDependencies.recipientCache.clear()
|
||||
AppDependencies.recipientCache.warmUp()
|
||||
SignalDatabase.threads.clearCache()
|
||||
|
||||
@@ -56,16 +56,11 @@ class RemappedRecordTables internal constructor(context: Context?, databaseHelpe
|
||||
fun getAllRecipientMappings(): Map<RecipientId, RecipientId> {
|
||||
val recipientMap: MutableMap<RecipientId, RecipientId> = HashMap()
|
||||
|
||||
readableDatabase.withinTransaction { db ->
|
||||
trimInvalidRecipientEntries(db)
|
||||
trimInvalidThreadEntries(db)
|
||||
|
||||
val mappings = getAllMappings(db, Recipients.TABLE_NAME)
|
||||
for (mapping in mappings) {
|
||||
val oldId = RecipientId.from(mapping.oldId)
|
||||
val newId = RecipientId.from(mapping.newId)
|
||||
recipientMap[oldId] = newId
|
||||
}
|
||||
val mappings = getAllMappings(readableDatabase, Recipients.TABLE_NAME)
|
||||
for (mapping in mappings) {
|
||||
val oldId = RecipientId.from(mapping.oldId)
|
||||
val newId = RecipientId.from(mapping.newId)
|
||||
recipientMap[oldId] = newId
|
||||
}
|
||||
|
||||
return recipientMap
|
||||
@@ -74,16 +69,21 @@ class RemappedRecordTables internal constructor(context: Context?, databaseHelpe
|
||||
fun getAllThreadMappings(): Map<Long, Long> {
|
||||
val threadMap: MutableMap<Long, Long> = HashMap()
|
||||
|
||||
readableDatabase.withinTransaction { db ->
|
||||
val mappings = getAllMappings(db, Threads.TABLE_NAME)
|
||||
for (mapping in mappings) {
|
||||
threadMap[mapping.oldId] = mapping.newId
|
||||
}
|
||||
val mappings = getAllMappings(readableDatabase, Threads.TABLE_NAME)
|
||||
for (mapping in mappings) {
|
||||
threadMap[mapping.oldId] = mapping.newId
|
||||
}
|
||||
|
||||
return threadMap
|
||||
}
|
||||
|
||||
fun trimStaleMappings() {
|
||||
writableDatabase.withinTransaction { db ->
|
||||
trimInvalidRecipientEntries(db)
|
||||
trimInvalidThreadEntries(db)
|
||||
}
|
||||
}
|
||||
|
||||
fun addRecipientMapping(oldId: RecipientId, newId: RecipientId) {
|
||||
addMapping(Recipients.TABLE_NAME, Mapping(oldId.toLong(), newId.toLong()))
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.database;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.signal.network.util.Preconditions;
|
||||
@@ -11,6 +12,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Merging together recipients and threads is messy business. We can easily replace *almost* all of
|
||||
@@ -30,8 +32,10 @@ class RemappedRecords {
|
||||
|
||||
private static final RemappedRecords INSTANCE = new RemappedRecords();
|
||||
|
||||
private Map<RecipientId, RecipientId> recipientMap;
|
||||
private Map<Long, Long> threadMap;
|
||||
private volatile Map<RecipientId, RecipientId> recipientMap;
|
||||
private volatile Map<Long, Long> threadMap;
|
||||
|
||||
private final AtomicBoolean staleTrimScheduled = new AtomicBoolean(false);
|
||||
|
||||
private RemappedRecords() {}
|
||||
|
||||
@@ -106,13 +110,31 @@ class RemappedRecords {
|
||||
|
||||
private void ensureRecipientMapIsPopulated() {
|
||||
if (recipientMap == null) {
|
||||
recipientMap = SignalDatabase.remappedRecords().getAllRecipientMappings();
|
||||
Map<RecipientId, RecipientId> loaded = SignalDatabase.remappedRecords().getAllRecipientMappings();
|
||||
synchronized (this) {
|
||||
if (recipientMap == null) {
|
||||
recipientMap = loaded;
|
||||
}
|
||||
}
|
||||
scheduleStaleTrimIfNeeded(loaded.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureThreadMapIsPopulated() {
|
||||
if (threadMap == null) {
|
||||
threadMap = SignalDatabase.remappedRecords().getAllThreadMappings();
|
||||
Map<Long, Long> loaded = SignalDatabase.remappedRecords().getAllThreadMappings();
|
||||
synchronized (this) {
|
||||
if (threadMap == null) {
|
||||
threadMap = loaded;
|
||||
}
|
||||
}
|
||||
scheduleStaleTrimIfNeeded(loaded.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleStaleTrimIfNeeded(boolean loadedMapWasEmpty) {
|
||||
if (!loadedMapWasEmpty && staleTrimScheduled.compareAndSet(false, true)) {
|
||||
SignalExecutors.BOUNDED.execute(() -> SignalDatabase.remappedRecords().trimStaleMappings());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,7 @@ public final class JobManagerFactories {
|
||||
put(LocalPlaintextArchiveJob.KEY, new LocalPlaintextArchiveJob.Factory());
|
||||
put(LocalBackupJobApi29.KEY, new LocalBackupJobApi29.Factory());
|
||||
put(MarkerJob.KEY, new MarkerJob.Factory());
|
||||
put(MessageSendLogCleanupJob.KEY, new MessageSendLogCleanupJob.Factory());
|
||||
put(MultiDeviceAttachmentBackfillMissingJob.KEY, new MultiDeviceAttachmentBackfillMissingJob.Factory());
|
||||
put(MultiDeviceAttachmentBackfillUpdateJob.KEY, new MultiDeviceAttachmentBackfillUpdateJob.Factory());
|
||||
put(MultiDeviceBlockedUpdateJob.KEY, new MultiDeviceBlockedUpdateJob.Factory());
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.jobs
|
||||
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Trims expired entries out of the message send log after a delay.
|
||||
*/
|
||||
class MessageSendLogCleanupJob private constructor(parameters: Parameters) : Job(parameters) {
|
||||
companion object {
|
||||
const val KEY = "MessageSendLogCleanupJob"
|
||||
|
||||
@JvmStatic
|
||||
fun enqueue() {
|
||||
AppDependencies.jobManager.add(
|
||||
MessageSendLogCleanupJob(
|
||||
Parameters.Builder()
|
||||
.setInitialDelay(TimeUnit.MINUTES.toMillis(1))
|
||||
.setLifespan(TimeUnit.HOURS.toMillis(1))
|
||||
.setMaxInstancesForFactory(1)
|
||||
.setQueue(KEY)
|
||||
.build()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun serialize(): ByteArray? = null
|
||||
|
||||
override fun getFactoryKey(): String = KEY
|
||||
|
||||
override fun onFailure() = Unit
|
||||
|
||||
override fun run(): Result {
|
||||
SignalDatabase.messageLog.trimOldMessages(System.currentTimeMillis(), RemoteConfig.retryRespondMaxAge)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
class Factory : Job.Factory<MessageSendLogCleanupJob> {
|
||||
override fun create(parameters: Parameters, serializedData: ByteArray?): MessageSendLogCleanupJob {
|
||||
return MessageSendLogCleanupJob(parameters)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user