Fix thrashing storage service fields.

This commit is contained in:
Cody Henthorne
2026-05-27 14:01:28 -04:00
committed by Michelle Tang
parent ec07b7805e
commit 41f52ed886
6 changed files with 35 additions and 16 deletions
@@ -1121,6 +1121,12 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
put(USERNAME, update.new.proto.username.nullIfBlank())
put(STORAGE_SERVICE_ID, Base64.encodeWithPadding(update.new.id.raw))
if (SignalStore.account.isLinkedDevice) {
StorageSyncModels.remoteToLocalAvatarColor(update.new.proto.avatarColor)?.let {
put(AVATAR_COLOR, it.serialize())
}
}
if (update.new.proto.hasUnknownFields()) {
put(STORAGE_SERVICE_PROTO, Base64.encodeWithPadding(update.new.serializedUnknowns!!))
} else {
@@ -5,6 +5,7 @@ import okio.ByteString
import org.signal.core.util.isNotEmpty
import org.signal.core.util.logging.Log
import org.signal.core.util.nullIfEmpty
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.storage.StorageSyncHelper.applyAccountStorageSyncUpdates
import org.whispersystems.signalservice.api.storage.IAPSubscriptionId
@@ -138,6 +139,7 @@ class AccountRecordProcessor(
usernameLink = remote.proto.usernameLink
notificationProfileManualOverride = remote.proto.notificationProfileManualOverride
backupTier = local.proto.backupTier ?: remote.proto.backupTier
avatarColor = if (SignalStore.account.isPrimaryDevice) local.proto.avatarColor else remote.proto.avatarColor
automaticKeyVerificationDisabled = remote.proto.automaticKeyVerificationDisabled
hasSeenAdminDeleteEducationDialog = remote.proto.hasSeenAdminDeleteEducationDialog
releaseNotesChatArchived = remote.proto.releaseNotesChatArchived ?: local.proto.releaseNotesChatArchived
@@ -198,15 +198,27 @@ class ContactRecordProcessor(
local.proto.e164 != remote.proto.e164
if (e164sMatchButPnisDont) {
Log.w(TAG, "Matching E164s, but the PNIs differ! Trusting our local pair.")
// TODO [pnp] Schedule CDS fetch?
mergedPni = localPni
mergedE164 = local.proto.e164
if (SignalStore.account.isPrimaryDevice) {
Log.w(TAG, "Matching E164s, but the PNIs differ! Trusting our local pair.")
// TODO [pnp] Schedule CDS fetch?
mergedPni = localPni
mergedE164 = local.proto.e164
} else {
Log.w(TAG, "Matching E164s, but the PNIs differ! Linked device — trusting the remote pair.")
mergedPni = remotePni
mergedE164 = remote.proto.e164
}
} else if (pnisMatchButE164sDont) {
Log.w(TAG, "Matching PNIs, but the E164s differ! Trusting our local pair.")
// TODO [pnp] Schedule CDS fetch?
mergedPni = localPni
mergedE164 = local.proto.e164
if (SignalStore.account.isPrimaryDevice) {
Log.w(TAG, "Matching PNIs, but the E164s differ! Trusting our local pair.")
// TODO [pnp] Schedule CDS fetch?
mergedPni = localPni
mergedE164 = local.proto.e164
} else {
Log.w(TAG, "Matching PNIs, but the E164s differ! Linked device — trusting the remote pair.")
mergedPni = remotePni
mergedE164 = remote.proto.e164
}
} else {
mergedPni = remotePni ?: localPni
mergedE164 = remote.proto.e164.nullIfBlank() ?: local.proto.e164.nullIfBlank()
@@ -214,8 +226,10 @@ class ContactRecordProcessor(
val merged = SignalContactRecord.newBuilder(remote.serializedUnknowns).apply {
e164 = mergedE164 ?: ""
aci = local.proto.aci.nullIfBlank() ?: remote.proto.aci
pni = mergedPni?.toStringWithoutPrefix() ?: ""
aciBinary = local.proto.aciBinary.nullIfEmpty() ?: remote.proto.aciBinary
aci = ""
pniBinary = mergedPni?.toByteStringWithoutPrefix() ?: byteArrayOf().toByteString()
pni = ""
givenName = mergedProfileGivenName
familyName = mergedProfileFamilyName
profileKey = remote.proto.profileKey.nullIfEmpty()?.takeIf { ProfileKeyUtil.profileKeyOrNull(it.toByteArray()) != null } ?: local.proto.profileKey
@@ -237,8 +251,6 @@ class ContactRecordProcessor(
pniSignatureVerified = remote.proto.pniSignatureVerified || local.proto.pniSignatureVerified
note = remote.proto.note.nullIfBlank() ?: ""
avatarColor = if (SignalStore.account.isPrimaryDevice) local.proto.avatarColor else remote.proto.avatarColor
aciBinary = local.proto.aciBinary.nullIfEmpty() ?: remote.proto.aciBinary
pniBinary = mergedPni?.toByteStringWithoutPrefix() ?: byteArrayOf().toByteString()
}.build().toSignalContactRecord(StorageId.forContact(keyGenerator.generate()))
val matchesRemote = doParamsMatch(remote, merged)
@@ -181,7 +181,6 @@ object StorageSyncHelper {
)
}
hasBackup = SignalStore.backup.areBackupsEnabled && SignalStore.backup.hasBackupBeenUploaded
backupTier = when {
SignalStore.account.isLinkedDevice -> null
SignalStore.backup.areBackupsEnabled && SignalStore.backup.backupTier != null -> getBackupLevelValue(SignalStore.backup.backupTier!!)
@@ -192,8 +192,10 @@ object StorageSyncModels {
}
return SignalContactRecord.newBuilder(recipient.syncExtras.storageProto).apply {
aciBinary = recipient.aci?.toByteString() ?: ByteString.EMPTY
aci = ""
e164 = recipient.e164 ?: ""
pniBinary = recipient.pni?.toByteStringWithoutPrefix() ?: ByteString.EMPTY
pni = ""
profileKey = recipient.profileKey?.toByteString() ?: ByteString.EMPTY
givenName = recipient.signalProfileName.givenName
@@ -216,8 +218,6 @@ object StorageSyncModels {
nickname = recipient.nickname.takeUnless { it.isEmpty }?.let { ContactRecord.Name(given = it.givenName, family = it.familyName) }
note = recipient.note ?: ""
avatarColor = localToRemoteAvatarColor(recipient.avatarColor)
aciBinary = recipient.aci?.toByteString() ?: ByteString.EMPTY
pniBinary = recipient.pni?.toByteStringWithoutPrefix() ?: ByteString.EMPTY
}.build().toSignalContactRecord(StorageId.forContact(rawStorageId))
}