From 040240c4d232e96f9d7b746b760f659dffda53f6 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 22 Sep 2026 23:10:41 -0400 Subject: [PATCH] Periodically refresh attributes. --- .../securesms/ApplicationContext.java | 1 + .../securesms/jobs/RefreshAttributesJob.java | 20 +++++++++++++++++++ .../securesms/keyvalue/MiscellaneousValues.kt | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 1e399e27c9..5530497590 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -257,6 +257,7 @@ public class ApplicationContext extends Application implements AppForegroundObse .addPostRender(AccountConsistencyWorkerJob::enqueueIfNecessary) .addPostRender(GroupRingCleanupJob::enqueue) .addPostRender(LinkedDeviceInactiveCheckJob::enqueueIfNecessary) + .addPostRender(RefreshAttributesJob::enqueueIfNecessary) .addPostRender(() -> ActiveCallManager.clearNotifications(this)) .addPostRender(RestoreOptimizedMediaJob::enqueueIfNecessary) .addPostRender(() -> AppDependencies.getPinnedMessageManager().scheduleIfNecessary()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java index b72c014db2..21cc831899 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java @@ -11,6 +11,7 @@ import org.signal.core.util.logging.Log; import org.signal.network.exceptions.NonSuccessfulResponseCodeException; import org.thoughtcrime.securesms.AppCapabilities; import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; +import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; @@ -37,10 +38,27 @@ public class RefreshAttributesJob extends BaseJob { private static final String KEY_FORCED = "forced"; + private static final long REFRESH_INTERVAL = TimeUnit.DAYS.toMillis(7); + private static volatile boolean hasRefreshedThisAppCycle; private final boolean forced; + /** + * Enqueues a routine refresh if it's been long enough since our last successful one. + */ + public static void enqueueIfNecessary() { + if (!SignalStore.account().isRegistered()) { + return; + } + + long timeSinceLastRefresh = System.currentTimeMillis() - SignalStore.misc().getLastRefreshAttributesTime(); + + if (timeSinceLastRefresh > REFRESH_INTERVAL || timeSinceLastRefresh < 0) { + AppDependencies.getJobManager().add(new RefreshAttributesJob(false)); + } + } + public static RefreshAttributesJob forAccountRestore() { return new RefreshAttributesJob(true, Parameters.PRIORITY_HIGH); } @@ -98,6 +116,7 @@ public class RefreshAttributesJob extends BaseJob { if (!forced && hasRefreshedThisAppCycle) { Log.d(TAG, "Already refreshed this app cycle. Skipping."); + SignalStore.misc().setLastRefreshAttributesTime(System.currentTimeMillis()); return; } @@ -115,6 +134,7 @@ public class RefreshAttributesJob extends BaseJob { } hasRefreshedThisAppCycle = true; + SignalStore.misc().setLastRefreshAttributesTime(System.currentTimeMillis()); } private void setPrimaryDeviceAttributes(@NonNull SvrValues svrValues, @NonNull AccountAttributes.Capabilities capabilities) throws IOException { diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.kt index fa6a52f214..36b89fe0d7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.kt @@ -35,6 +35,7 @@ class MiscellaneousValues internal constructor(store: KeyValueStore) : SignalSto private const val FORCE_PNI_SIGNED_PREKEY_ROTATION = "misc.force_pni_signed_prekey_rotation" private const val LAST_CDS_FOREGROUND_SYNC = "misc.last_cds_foreground_sync" private const val LINKED_DEVICE_LAST_ACTIVE_CHECK_TIME = "misc.linked_device.last_active_check_time" + private const val LAST_REFRESH_ATTRIBUTES_TIME = "misc.last_refresh_attributes_time" private const val LEAST_ACTIVE_LINKED_DEVICE = "misc.linked_device.least_active" private const val NEXT_DATABASE_ANALYSIS_TIME = "misc.next_database_analysis_time" private const val LAST_NETWORK_RESET_TIME = "misc.last_network_reset_time" @@ -277,6 +278,11 @@ class MiscellaneousValues internal constructor(store: KeyValueStore) : SignalSto */ var linkedDeviceLastActiveCheckTime by longValue(LINKED_DEVICE_LAST_ACTIVE_CHECK_TIME, 0) + /** + * The last time we successfully refreshed our account attributes with the service. + */ + var lastRefreshAttributesTime: Long by longValue(LAST_REFRESH_ATTRIBUTES_TIME, 0) + /** * Details about the least-active linked device. */