diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt index 344fb8658c..a883d5a19e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt @@ -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 { diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/AccountRecordProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/storage/AccountRecordProcessor.kt index e0b9fd52e4..115d62df4f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/AccountRecordProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/AccountRecordProcessor.kt @@ -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 diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/ContactRecordProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/storage/ContactRecordProcessor.kt index 9adda3aed3..23b5462748 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/ContactRecordProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/ContactRecordProcessor.kt @@ -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) diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.kt b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.kt index 23f0c2a232..e0240a99fe 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.kt @@ -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!!) diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncModels.kt b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncModels.kt index 187a142bbb..ef607bc515 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncModels.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncModels.kt @@ -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)) } diff --git a/lib/libsignal-service/src/main/protowire/StorageService.proto b/lib/libsignal-service/src/main/protowire/StorageService.proto index 2ef121affc..0072714a29 100644 --- a/lib/libsignal-service/src/main/protowire/StorageService.proto +++ b/lib/libsignal-service/src/main/protowire/StorageService.proto @@ -292,7 +292,7 @@ message AccountRecord { reserved /* backupsSubscriberId */ 36; reserved /* backupsSubscriberCurrencyCode */ 37; reserved /* backupsSubscriptionManuallyCancelled */ 38; - optional bool hasBackup = 39; // Set to true after backups are enabled and one is uploaded. + reserved /* hasBackup */ 39; optional uint64 backupTier = 40; // See zkgroup for integer particular values. Unset if backups are not enabled. IAPSubscriberData backupSubscriberData = 41; optional AvatarColor avatarColor = 42;