mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-23 11:15:44 +00:00
Insert session switchover events when appropriate.
This commit is contained in:
@@ -73,6 +73,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateD
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExportState;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileChangeDetails;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.SessionSwitchoverEvent;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange;
|
||||
import org.thoughtcrime.securesms.insights.InsightsConstants;
|
||||
@@ -94,6 +95,7 @@ import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.stories.Stories;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.JsonUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
@@ -1125,6 +1127,26 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
|
||||
ApplicationDependencies.getDatabaseObserver().notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
public void insertSessionSwitchoverEvent(@NonNull RecipientId recipientId, long threadId, @NonNull SessionSwitchoverEvent event) {
|
||||
if (!FeatureFlags.phoneNumberPrivacy()) {
|
||||
throw new IllegalStateException("Should not occur in a non-PNP world!");
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(RECIPIENT_ID, recipientId.serialize());
|
||||
values.put(RECIPIENT_DEVICE_ID, 1);
|
||||
values.put(DATE_RECEIVED, System.currentTimeMillis());
|
||||
values.put(DATE_SENT, System.currentTimeMillis());
|
||||
values.put(READ, 1);
|
||||
values.put(TYPE, MessageTypes.SESSION_SWITCHOVER_TYPE);
|
||||
values.put(THREAD_ID, threadId);
|
||||
values.put(BODY, Base64.encodeBytes(event.toByteArray()));
|
||||
|
||||
getWritableDatabase().insert(TABLE_NAME, null, values);
|
||||
|
||||
ApplicationDependencies.getDatabaseObserver().notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
public void insertSmsExportMessage(@NonNull RecipientId recipientId, long threadId) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(RECIPIENT_ID, recipientId.serialize());
|
||||
|
||||
@@ -50,6 +50,7 @@ public interface MessageTypes {
|
||||
long BOOST_REQUEST_TYPE = 15;
|
||||
long THREAD_MERGE_TYPE = 16;
|
||||
long SMS_EXPORT_TYPE = 17;
|
||||
long SESSION_SWITCHOVER_TYPE = 18;
|
||||
|
||||
long BASE_INBOX_TYPE = 20;
|
||||
long BASE_OUTBOX_TYPE = 21;
|
||||
@@ -207,6 +208,10 @@ public interface MessageTypes {
|
||||
return (type & BASE_TYPE_MASK) == THREAD_MERGE_TYPE;
|
||||
}
|
||||
|
||||
static boolean isSessionSwitchoverType(long type) {
|
||||
return (type & BASE_TYPE_MASK) == SESSION_SWITCHOVER_TYPE;
|
||||
}
|
||||
|
||||
static boolean isSecureType(long type) {
|
||||
return (type & SECURE_MESSAGE_BIT) != 0;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ data class PnpDataSet(
|
||||
* Applies the set of operations and returns the resulting dataset.
|
||||
* Important: This only occurs _in memory_. You must still apply the operations to disk to persist them.
|
||||
*/
|
||||
fun perform(operations: List<PnpOperation>): PnpDataSet {
|
||||
fun perform(operations: LinkedHashSet<PnpOperation>): PnpDataSet {
|
||||
if (operations.isEmpty()) {
|
||||
return this
|
||||
}
|
||||
@@ -136,7 +136,7 @@ data class PnpDataSet(
|
||||
*/
|
||||
data class PnpChangeSet(
|
||||
val id: PnpIdResolver,
|
||||
val operations: List<PnpOperation> = emptyList(),
|
||||
val operations: LinkedHashSet<PnpOperation> = linkedSetOf(),
|
||||
val breadCrumbs: List<String> = emptyList()
|
||||
) {
|
||||
// We want to exclude breadcrumbs from equality for testing purposes
|
||||
@@ -213,7 +213,8 @@ sealed class PnpOperation {
|
||||
}
|
||||
|
||||
data class SessionSwitchoverInsert(
|
||||
override val recipientId: RecipientId
|
||||
override val recipientId: RecipientId,
|
||||
val e164: String?
|
||||
) : PnpOperation()
|
||||
|
||||
data class ChangeNumberInsert(
|
||||
|
||||
@@ -66,6 +66,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.ChatColor
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ExpiringProfileKeyCredentialColumnData
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.RecipientExtras
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.SessionSwitchoverEvent
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.Wallpaper
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
@@ -2367,7 +2368,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
affectedIds = affectedIds,
|
||||
oldIds = oldIds,
|
||||
changedNumberId = changedNumberId,
|
||||
operations = changeSet.operations,
|
||||
operations = changeSet.operations.toList(),
|
||||
breadCrumbs = changeSet.breadCrumbs
|
||||
)
|
||||
}
|
||||
@@ -2436,8 +2437,14 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
merge(operation.primaryId, operation.secondaryId, inputPni)
|
||||
}
|
||||
is PnpOperation.SessionSwitchoverInsert -> {
|
||||
// TODO [pnp]
|
||||
Log.w(TAG, "Session switchover events aren't implemented yet!")
|
||||
val threadId: Long? = threads.getThreadIdFor(operation.recipientId)
|
||||
if (threadId != null) {
|
||||
val event = SessionSwitchoverEvent
|
||||
.newBuilder()
|
||||
.setE164(operation.e164 ?: "")
|
||||
.build()
|
||||
SignalDatabase.messages.insertSessionSwitchoverEvent(operation.recipientId, threadId, event)
|
||||
}
|
||||
}
|
||||
is PnpOperation.ChangeNumberInsert -> {
|
||||
if (changeSet.id is PnpIdResolver.PnpNoopId) {
|
||||
@@ -2544,7 +2551,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
check(fullData.commonId == null)
|
||||
check(listOfNotNull(fullData.byE164, fullData.byPniSid, fullData.byPniOnly, fullData.byAciSid).size >= 2)
|
||||
|
||||
val operations: MutableList<PnpOperation> = mutableListOf()
|
||||
val operations: LinkedHashSet<PnpOperation> = linkedSetOf()
|
||||
|
||||
operations += processPossibleE164PniSidMerge(pni, pniVerified, fullData, breadCrumbs)
|
||||
operations += processPossiblePniSidAciSidMerge(e164, pni, aci, fullData.perform(operations), changeSelf, breadCrumbs)
|
||||
@@ -2559,6 +2566,13 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
recipientId = primaryId,
|
||||
aci = aci
|
||||
)
|
||||
|
||||
if (!pniVerified && finalData.pni != null && sessions.hasAnySessionFor(finalData.pni.toString())) {
|
||||
operations += PnpOperation.SessionSwitchoverInsert(
|
||||
recipientId = primaryId,
|
||||
e164 = finalData.e164
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (finalData.byE164 == null && e164 != null && (changeSelf || notSelf(e164, pni, aci))) {
|
||||
@@ -2599,7 +2613,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
private fun processNonMergePnpUpdate(e164: String?, pni: PNI?, aci: ACI?, pniVerified: Boolean, changeSelf: Boolean, commonId: RecipientId, breadCrumbs: MutableList<String>): PnpChangeSet {
|
||||
val record: RecipientRecord = getRecord(commonId)
|
||||
|
||||
val operations: MutableList<PnpOperation> = mutableListOf()
|
||||
val operations: LinkedHashSet<PnpOperation> = linkedSetOf()
|
||||
|
||||
// This is a special case. The ACI passed in doesn't match the common record. We can't change ACIs, so we need to make a new record.
|
||||
if (aci != null && aci != record.serviceId && record.serviceId != null && !record.sidIsPni()) {
|
||||
@@ -2658,7 +2672,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
val newServiceId: ServiceId? = aci ?: pni ?: record.serviceId
|
||||
|
||||
if (!pniVerified && record.serviceId != null && record.serviceId != newServiceId && sessions.hasAnySessionFor(record.serviceId.toString())) {
|
||||
operations += PnpOperation.SessionSwitchoverInsert(commonId)
|
||||
operations += PnpOperation.SessionSwitchoverInsert(recipientId = commonId, e164 = record.e164 ?: e164)
|
||||
}
|
||||
|
||||
return PnpChangeSet(
|
||||
@@ -2668,15 +2682,15 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
)
|
||||
}
|
||||
|
||||
private fun processPossibleE164PniSidMerge(pni: PNI?, pniVerified: Boolean, data: PnpDataSet, breadCrumbs: MutableList<String>): List<PnpOperation> {
|
||||
private fun processPossibleE164PniSidMerge(pni: PNI?, pniVerified: Boolean, data: PnpDataSet, breadCrumbs: MutableList<String>): LinkedHashSet<PnpOperation> {
|
||||
if (pni == null || data.byE164 == null || data.byPniSid == null || data.e164Record == null || data.pniSidRecord == null || data.e164Record.id == data.pniSidRecord.id) {
|
||||
return emptyList()
|
||||
return linkedSetOf()
|
||||
}
|
||||
|
||||
// We have found records for both the E164 and PNI, and they're different
|
||||
breadCrumbs += "E164PniSidMerge"
|
||||
|
||||
val operations: MutableList<PnpOperation> = mutableListOf()
|
||||
val operations: LinkedHashSet<PnpOperation> = linkedSetOf()
|
||||
|
||||
// The PNI record only has a single identifier. We know we must merge.
|
||||
if (data.pniSidRecord.sidOnly(pni)) {
|
||||
@@ -2704,31 +2718,35 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
)
|
||||
|
||||
if (!pniVerified && sessions.hasAnySessionFor(data.pniSidRecord.serviceId.toString())) {
|
||||
operations += PnpOperation.SessionSwitchoverInsert(data.byPniSid)
|
||||
operations += PnpOperation.SessionSwitchoverInsert(recipientId = data.byPniSid, e164 = data.pniSidRecord.e164)
|
||||
|
||||
if (data.e164Record.serviceId == null || data.e164Record.sidIsPni()) {
|
||||
operations += PnpOperation.SessionSwitchoverInsert(recipientId = data.byE164, e164 = data.e164Record.e164)
|
||||
}
|
||||
}
|
||||
|
||||
if (!pniVerified && data.e164Record.serviceId != null && data.e164Record.sidIsPni() && sessions.hasAnySessionFor(data.e164Record.serviceId.toString())) {
|
||||
operations += PnpOperation.SessionSwitchoverInsert(data.byE164)
|
||||
operations += PnpOperation.SessionSwitchoverInsert(recipientId = data.byE164, e164 = data.e164)
|
||||
}
|
||||
}
|
||||
|
||||
return operations
|
||||
}
|
||||
|
||||
private fun processPossiblePniSidAciSidMerge(e164: String?, pni: PNI?, aci: ACI?, data: PnpDataSet, changeSelf: Boolean, breadCrumbs: MutableList<String>): List<PnpOperation> {
|
||||
private fun processPossiblePniSidAciSidMerge(e164: String?, pni: PNI?, aci: ACI?, data: PnpDataSet, changeSelf: Boolean, breadCrumbs: MutableList<String>): LinkedHashSet<PnpOperation> {
|
||||
if (pni == null || aci == null || data.byPniSid == null || data.byAciSid == null || data.pniSidRecord == null || data.aciSidRecord == null || data.pniSidRecord.id == data.aciSidRecord.id) {
|
||||
return emptyList()
|
||||
return linkedSetOf()
|
||||
}
|
||||
|
||||
if (!changeSelf && isSelf(e164, pni, aci)) {
|
||||
breadCrumbs += "ChangeSelfPreventsPniSidAciSidMerge"
|
||||
return emptyList()
|
||||
return linkedSetOf()
|
||||
}
|
||||
|
||||
// We have found records for both the PNI and ACI, and they're different
|
||||
breadCrumbs += "PniSidAciSidMerge"
|
||||
|
||||
val operations: MutableList<PnpOperation> = mutableListOf()
|
||||
val operations: LinkedHashSet<PnpOperation> = linkedSetOf()
|
||||
|
||||
// The PNI record only has a single identifier. We know we must merge.
|
||||
if (data.pniSidRecord.sidOnly(pni)) {
|
||||
|
||||
@@ -86,7 +86,7 @@ public final class FeatureFlags {
|
||||
private static final String USE_HARDWARE_AEC_IF_OLD = "android.calling.useHardwareAecIfOlderThanApi29";
|
||||
private static final String USE_AEC3 = "android.calling.useAec3";
|
||||
private static final String PAYMENTS_COUNTRY_BLOCKLIST = "android.payments.blocklist";
|
||||
private static final String PHONE_NUMBER_PRIVACY = "android.pnp";
|
||||
public static final String PHONE_NUMBER_PRIVACY = "android.pnp";
|
||||
private static final String USE_FCM_FOREGROUND_SERVICE = "android.useFcmForegroundService.3";
|
||||
private static final String STORIES_AUTO_DOWNLOAD_MAXIMUM = "android.stories.autoDownloadMaximum";
|
||||
private static final String TELECOM_MANUFACTURER_ALLOWLIST = "android.calling.telecomAllowList";
|
||||
|
||||
Reference in New Issue
Block a user