mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 08:39:22 +01:00
Add Change Number capability and Conversation Update item.
This commit is contained in:
committed by
Greyson Parrelli
parent
bb446ac1d5
commit
77ff25ec49
@@ -167,6 +167,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
|
||||
public abstract long insertMessageOutbox(@NonNull OutgoingMediaMessage message, long threadId, boolean forceSms, int defaultReceiptStatus, @Nullable SmsDatabase.InsertListener insertListener) throws MmsException;
|
||||
public abstract void insertProfileNameChangeMessages(@NonNull Recipient recipient, @NonNull String newProfileName, @NonNull String previousProfileName);
|
||||
public abstract void insertGroupV1MigrationEvents(@NonNull RecipientId recipientId, long threadId, @NonNull GroupMigrationMembershipChange membershipChange);
|
||||
public abstract void insertNumberChangeMessages(@NonNull Recipient recipient);
|
||||
|
||||
public abstract boolean deleteMessage(long messageId);
|
||||
abstract void deleteThread(long threadId);
|
||||
|
||||
@@ -503,6 +503,11 @@ public class MmsDatabase extends MessageDatabase {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertNumberChangeMessages(@NonNull Recipient recipient) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTransaction(SQLiteDatabase database) {
|
||||
database.endTransaction();
|
||||
|
||||
@@ -77,6 +77,7 @@ public interface MmsSmsColumns {
|
||||
protected static final long OUTGOING_VIDEO_CALL_TYPE = 11;
|
||||
protected static final long GROUP_CALL_TYPE = 12;
|
||||
protected static final long BAD_DECRYPT_TYPE = 13;
|
||||
protected static final long CHANGE_NUMBER_TYPE = 14;
|
||||
|
||||
protected static final long BASE_INBOX_TYPE = 20;
|
||||
protected static final long BASE_OUTBOX_TYPE = 21;
|
||||
@@ -334,6 +335,10 @@ public interface MmsSmsColumns {
|
||||
return type == GV1_MIGRATION_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isChangeNumber(long type) {
|
||||
return type == CHANGE_NUMBER_TYPE;
|
||||
}
|
||||
|
||||
public static long translateFromSystemBaseType(long theirType) {
|
||||
// public static final int NONE_TYPE = 0;
|
||||
// public static final int INBOX_TYPE = 1;
|
||||
|
||||
@@ -108,7 +108,7 @@ public class MmsSmsDatabase extends Database {
|
||||
MmsSmsColumns.RECEIPT_TIMESTAMP};
|
||||
|
||||
private static final String SNIPPET_QUERY = "SELECT " + MmsSmsColumns.ID + ", 0 AS " + TRANSPORT + ", " + SmsDatabase.TYPE + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + SmsDatabase.TABLE_NAME + " " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ") " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ", " + SmsDatabase.Types.CHANGE_NUMBER_TYPE + ") " +
|
||||
"UNION ALL " +
|
||||
"SELECT " + MmsSmsColumns.ID + ", 1 AS " + TRANSPORT + ", " + MmsDatabase.MESSAGE_BOX + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME + " " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? " +
|
||||
|
||||
@@ -29,9 +29,9 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper;
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ChatColor;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime;
|
||||
@@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.v2.ProfileKeySet;
|
||||
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
|
||||
import org.thoughtcrime.securesms.jobs.RecipientChangedNumberJob;
|
||||
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
||||
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
|
||||
@@ -59,6 +60,7 @@ import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
import org.thoughtcrime.securesms.util.SqlUtil;
|
||||
import org.thoughtcrime.securesms.util.StringUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaperFactory;
|
||||
@@ -167,6 +169,7 @@ public class RecipientDatabase extends Database {
|
||||
static final int GROUPS_V1_MIGRATION = 1;
|
||||
static final int SENDER_KEY = 2;
|
||||
static final int ANNOUNCEMENT_GROUPS = 3;
|
||||
static final int CHANGE_NUMBER = 4;
|
||||
}
|
||||
|
||||
private static final String[] RECIPIENT_PROJECTION = new String[] {
|
||||
@@ -421,12 +424,17 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
|
||||
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust) {
|
||||
return getAndPossiblyMerge(uuid, e164, highTrust, false);
|
||||
}
|
||||
|
||||
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust, boolean changeSelf) {
|
||||
if (uuid == null && e164 == null) {
|
||||
throw new IllegalArgumentException("Must provide a UUID or E164!");
|
||||
}
|
||||
|
||||
RecipientId recipientNeedingRefresh = null;
|
||||
Pair<RecipientId, RecipientId> remapped = null;
|
||||
RecipientId recipientChangedNumber = null;
|
||||
boolean transactionSuccessful = false;
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
@@ -485,9 +493,15 @@ public class RecipientDatabase extends Database {
|
||||
} else if (!byE164.isPresent() && byUuid.isPresent()) {
|
||||
if (e164 != null) {
|
||||
if (highTrust) {
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). High-trust, so updating.", e164, byUuid.get()), true);
|
||||
setPhoneNumberOrThrow(byUuid.get(), e164);
|
||||
finalId = byUuid.get();
|
||||
if (Objects.equals(uuid, TextSecurePreferences.getLocalUuid(context)) && !changeSelf) {
|
||||
Log.w(TAG, String.format(Locale.US, "Found out about an E164 (%s) for our own UUID user (%s). High-trust but not change self, doing nothing.", e164, byUuid.get()), true);
|
||||
finalId = byUuid.get();
|
||||
} else {
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). High-trust, so updating.", e164, byUuid.get()), true);
|
||||
setPhoneNumberOrThrow(byUuid.get(), e164);
|
||||
finalId = byUuid.get();
|
||||
recipientChangedNumber = finalId;
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). Low-trust, so doing nothing.", e164, byUuid.get()), true);
|
||||
finalId = byUuid.get();
|
||||
@@ -552,6 +566,10 @@ public class RecipientDatabase extends Database {
|
||||
StorageSyncHelper.scheduleSyncForDataChange();
|
||||
RecipientId.clearCache();
|
||||
}
|
||||
|
||||
if (recipientChangedNumber != null) {
|
||||
ApplicationDependencies.getJobManager().add(new RecipientChangedNumberJob(recipientChangedNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1616,6 +1634,7 @@ public class RecipientDatabase extends Database {
|
||||
value = Bitmask.update(value, Capabilities.GROUPS_V1_MIGRATION, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isGv1Migration()).serialize());
|
||||
value = Bitmask.update(value, Capabilities.SENDER_KEY, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isSenderKey()).serialize());
|
||||
value = Bitmask.update(value, Capabilities.ANNOUNCEMENT_GROUPS, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isAnnouncementGroup()).serialize());
|
||||
value = Bitmask.update(value, Capabilities.CHANGE_NUMBER, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isChangeNumber()).serialize());
|
||||
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(CAPABILITIES, value);
|
||||
@@ -2040,7 +2059,7 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
try {
|
||||
RecipientId id = Recipient.self().getId();
|
||||
RecipientId newId = getAndPossiblyMerge(Recipient.self().requireUuid(), e164, true);
|
||||
RecipientId newId = getAndPossiblyMerge(Recipient.self().requireUuid(), e164, true, true);
|
||||
|
||||
if (id.equals(newId)) {
|
||||
Log.i(TAG, "[updateSelfPhone] Phone updated for self");
|
||||
@@ -3159,6 +3178,7 @@ public class RecipientDatabase extends Database {
|
||||
private final Recipient.Capability groupsV1MigrationCapability;
|
||||
private final Recipient.Capability senderKeyCapability;
|
||||
private final Recipient.Capability announcementGroupCapability;
|
||||
private final Recipient.Capability changeNumberCapability;
|
||||
private final InsightsBannerTier insightsBannerTier;
|
||||
private final byte[] storageId;
|
||||
private final MentionSetting mentionSetting;
|
||||
@@ -3251,6 +3271,7 @@ public class RecipientDatabase extends Database {
|
||||
this.groupsV1MigrationCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.GROUPS_V1_MIGRATION, Capabilities.BIT_LENGTH));
|
||||
this.senderKeyCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.SENDER_KEY, Capabilities.BIT_LENGTH));
|
||||
this.announcementGroupCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.ANNOUNCEMENT_GROUPS, Capabilities.BIT_LENGTH));
|
||||
this.changeNumberCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.CHANGE_NUMBER, Capabilities.BIT_LENGTH));
|
||||
this.insightsBannerTier = insightsBannerTier;
|
||||
this.storageId = storageId;
|
||||
this.mentionSetting = mentionSetting;
|
||||
@@ -3408,6 +3429,10 @@ public class RecipientDatabase extends Database {
|
||||
return announcementGroupCapability;
|
||||
}
|
||||
|
||||
public @NonNull Recipient.Capability getChangeNumberCapability() {
|
||||
return changeNumberCapability;
|
||||
}
|
||||
|
||||
public @Nullable byte[] getStorageId() {
|
||||
return storageId;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -270,8 +271,8 @@ public class SmsDatabase extends MessageDatabase {
|
||||
}
|
||||
|
||||
private @NonNull SqlUtil.Query buildMeaningfulMessagesQuery(long threadId) {
|
||||
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND TYPE != ?)";
|
||||
return SqlUtil.buildQuery(query, threadId, IGNORABLE_TYPESMASK_WHEN_COUNTING, Types.PROFILE_CHANGE_TYPE);
|
||||
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND TYPE != ? AND TYPE != ?)";
|
||||
return SqlUtil.buildQuery(query, threadId, IGNORABLE_TYPESMASK_WHEN_COUNTING, Types.PROFILE_CHANGE_TYPE, Types.CHANGE_NUMBER_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1027,6 +1028,53 @@ public class SmsDatabase extends MessageDatabase {
|
||||
databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertNumberChangeMessages(@NonNull Recipient recipient) {
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
List<GroupDatabase.GroupRecord> groupRecords = DatabaseFactory.getGroupDatabase(context).getGroupsContainingMember(recipient.getId(), false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
try {
|
||||
threadIdsToUpdate.add(threadDatabase.getThreadIdFor(recipient.getId()));
|
||||
for (GroupDatabase.GroupRecord groupRecord : groupRecords) {
|
||||
if (groupRecord.isActive()) {
|
||||
threadIdsToUpdate.add(threadDatabase.getThreadIdFor(groupRecord.getRecipientId()));
|
||||
}
|
||||
}
|
||||
|
||||
threadIdsToUpdate.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(threadId -> {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(RECIPIENT_ID, recipient.getId().serialize());
|
||||
values.put(ADDRESS_DEVICE_ID, 1);
|
||||
values.put(DATE_RECEIVED, System.currentTimeMillis());
|
||||
values.put(DATE_SENT, System.currentTimeMillis());
|
||||
values.put(READ, 1);
|
||||
values.put(TYPE, Types.CHANGE_NUMBER_TYPE);
|
||||
values.put(THREAD_ID, threadId);
|
||||
values.putNull(BODY);
|
||||
|
||||
db.insert(TABLE_NAME, null, values);
|
||||
});
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
threadIdsToUpdate.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(threadId -> {
|
||||
TrimThreadJob.enqueueAsync(threadId);
|
||||
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
|
||||
notifyConversationListeners(threadId);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long type) {
|
||||
if (message.isJoined()) {
|
||||
|
||||
@@ -1514,7 +1514,8 @@ public class ThreadDatabase extends Database {
|
||||
|
||||
private boolean isSilentType(long type) {
|
||||
return MmsSmsColumns.Types.isProfileChange(type) ||
|
||||
MmsSmsColumns.Types.isGroupV1MigrationEvent(type);
|
||||
MmsSmsColumns.Types.isGroupV1MigrationEvent(type) ||
|
||||
MmsSmsColumns.Types.isChangeNumber(type);
|
||||
}
|
||||
|
||||
public Reader readerFor(Cursor cursor) {
|
||||
|
||||
@@ -178,6 +178,10 @@ public abstract class DisplayRecord {
|
||||
return SmsDatabase.Types.isProfileChange(type);
|
||||
}
|
||||
|
||||
public boolean isChangeNumber() {
|
||||
return SmsDatabase.Types.isChangeNumber(type);
|
||||
}
|
||||
|
||||
public int getDeliveryStatus() {
|
||||
return deliveryStatus;
|
||||
}
|
||||
|
||||
@@ -187,6 +187,8 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
} else if (isProfileChange()) {
|
||||
return staticUpdateDescription(getProfileChangeDescription(context), R.drawable.ic_update_profile_16);
|
||||
} else if (isChangeNumber()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_changed_their_number_to_a_new_number, r.getDisplayName(context)), R.drawable.ic_phone_16);
|
||||
} else if (isEndSession()) {
|
||||
if (isOutgoing()) return staticUpdateDescription(context.getString(R.string.SmsMessageRecord_secure_session_reset), R.drawable.ic_update_info_16);
|
||||
else return fromRecipient(getIndividualRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
@@ -484,7 +486,8 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
public boolean isUpdate() {
|
||||
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
|
||||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
|
||||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType();
|
||||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType() ||
|
||||
isChangeNumber();
|
||||
}
|
||||
|
||||
public boolean isMediaPending() {
|
||||
|
||||
Reference in New Issue
Block a user