Store the server timestamp for a message.

This commit is contained in:
Greyson Parrelli 2020-04-13 19:02:50 -04:00
parent 00b6a222bd
commit f12a9b9ac7
23 changed files with 315 additions and 214 deletions

View file

@ -52,6 +52,7 @@ public class MediaDatabase extends Database {
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.MESSAGE_BOX + ", "
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_SENT + ", "
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_RECEIVED + ", "
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_SERVER + ", "
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.THREAD_ID + ", "
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.RECIPIENT_ID + ", "
+ ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID + " as " + THREAD_RECIPIENT_ID + " "

View file

@ -118,6 +118,7 @@ public class MmsDatabase extends MessagingDatabase {
THREAD_ID + " INTEGER, " +
DATE_SENT + " INTEGER, " +
DATE_RECEIVED + " INTEGER, " +
DATE_SERVER + " INTEGER DEFAULT -1, " +
MESSAGE_BOX + " INTEGER, " +
READ + " INTEGER DEFAULT 0, " +
"m_id" + " TEXT, " +
@ -175,6 +176,7 @@ public class MmsDatabase extends MessagingDatabase {
"CREATE INDEX IF NOT EXISTS mms_read_and_notified_and_thread_id_index ON " + TABLE_NAME + "(" + READ + "," + NOTIFIED + "," + THREAD_ID + ");",
"CREATE INDEX IF NOT EXISTS mms_message_box_index ON " + TABLE_NAME + " (" + MESSAGE_BOX + ");",
"CREATE INDEX IF NOT EXISTS mms_date_sent_index ON " + TABLE_NAME + " (" + DATE_SENT + ");",
"CREATE INDEX IF NOT EXISTS mms_date_server_index ON " + TABLE_NAME + " (" + DATE_SERVER + ");",
"CREATE INDEX IF NOT EXISTS mms_thread_date_index ON " + TABLE_NAME + " (" + THREAD_ID + ", " + DATE_RECEIVED + ");",
"CREATE INDEX IF NOT EXISTS mms_reactions_unread_index ON " + TABLE_NAME + " (" + REACTIONS_UNREAD + ");"
};
@ -183,6 +185,7 @@ public class MmsDatabase extends MessagingDatabase {
MmsDatabase.TABLE_NAME + "." + ID + " AS " + ID,
THREAD_ID, DATE_SENT + " AS " + NORMALIZED_DATE_SENT,
DATE_RECEIVED + " AS " + NORMALIZED_DATE_RECEIVED,
DATE_SERVER,
MESSAGE_BOX, READ,
CONTENT_LOCATION, EXPIRY, MESSAGE_TYPE,
MESSAGE_SIZE, STATUS, TRANSACTION_ID,
@ -902,6 +905,7 @@ public class MmsDatabase extends MessagingDatabase {
ContentValues contentValues = new ContentValues();
contentValues.put(DATE_SENT, retrieved.getSentTimeMillis());
contentValues.put(DATE_SERVER, retrieved.getServerTimeMillis());
contentValues.put(RECIPIENT_ID, retrieved.getFrom().serialize());
contentValues.put(MESSAGE_BOX, mailbox);
@ -991,7 +995,6 @@ public class MmsDatabase extends MessagingDatabase {
Log.i(TAG, "Message received type: " + notification.getMessageType());
contentBuilder.add(CONTENT_LOCATION, notification.getContentLocation());
contentBuilder.add(DATE_SENT, System.currentTimeMillis());
contentBuilder.add(EXPIRY, notification.getExpiry());
@ -1474,13 +1477,20 @@ public class MmsDatabase extends MessagingDatabase {
public MessageRecord getCurrent() {
SlideDeck slideDeck = new SlideDeck(context, message.getAttachments());
return new MediaMmsMessageRecord(id, message.getRecipient(), message.getRecipient(),
1, System.currentTimeMillis(), System.currentTimeMillis(),
0, threadId, message.getBody(),
slideDeck, slideDeck.getSlides().size(),
return new MediaMmsMessageRecord(id,
message.getRecipient(),
message.getRecipient(),
1,
System.currentTimeMillis(),
System.currentTimeMillis(),
-1,
0,
threadId, message.getBody(),
slideDeck,
slideDeck.getSlides().size(),
message.isSecure() ? MmsSmsColumns.Types.getOutgoingEncryptedMessageType() : MmsSmsColumns.Types.getOutgoingSmsMessageType(),
new LinkedList<IdentityKeyMismatch>(),
new LinkedList<NetworkFailure>(),
new LinkedList<>(),
new LinkedList<>(),
message.getSubscriptionId(),
message.getExpiresIn(),
System.currentTimeMillis(),
@ -1493,7 +1503,10 @@ public class MmsDatabase extends MessagingDatabase {
message.getOutgoingQuote().isOriginalMissing(),
new SlideDeck(context, message.getOutgoingQuote().getAttachments())) :
null,
message.getSharedContacts(), message.getLinkPreviews(), false, Collections.emptyList());
message.getSharedContacts(),
message.getLinkPreviews(),
false,
Collections.emptyList());
}
}
@ -1565,22 +1578,23 @@ public class MmsDatabase extends MessagingDatabase {
}
private MediaMmsMessageRecord getMediaMmsMessageRecord(Cursor cursor) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID ));
long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_SENT ));
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID));
long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_SENT));
long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED));
long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX ));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID ));
long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.RECIPIENT_ID ));
int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS_DEVICE_ID ));
long dateServer = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.DATE_SERVER));
long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID));
long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.RECIPIENT_ID));
int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS_DEVICE_ID));
int deliveryReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.DELIVERY_RECEIPT_COUNT));
int readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.READ_RECEIPT_COUNT ));
String body = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.BODY ));
int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT ));
int readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.READ_RECEIPT_COUNT));
String body = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.BODY));
int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT));
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE ));
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.SUBSCRIPTION_ID ));
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRES_IN ));
long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRE_STARTED ));
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.SUBSCRIPTION_ID));
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRES_IN));
long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRE_STARTED));
boolean unidentified = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.UNIDENTIFIED)) == 1;
boolean isViewOnce = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.VIEW_ONCE)) == 1;
List<ReactionRecord> reactions = parseReactions(cursor);
@ -1601,7 +1615,7 @@ public class MmsDatabase extends MessagingDatabase {
Quote quote = getQuote(cursor);
return new MediaMmsMessageRecord(id, recipient, recipient,
addressDeviceId, dateSent, dateReceived, deliveryReceiptCount,
addressDeviceId, dateSent, dateReceived, dateServer, deliveryReceiptCount,
threadId, body, slideDeck, partCount, box, mismatches,
networkFailures, subscriptionId, expiresIn, expireStarted,
isViewOnce, readReceiptCount, quote, contacts, previews, unidentified, reactions);

View file

@ -6,6 +6,7 @@ public interface MmsSmsColumns {
public static final String ID = "_id";
public static final String NORMALIZED_DATE_SENT = "date_sent";
public static final String NORMALIZED_DATE_RECEIVED = "date_received";
public static final String DATE_SERVER = "date_server";
public static final String THREAD_ID = "thread_id";
public static final String READ = "read";
public static final String BODY = "body";

View file

@ -44,19 +44,27 @@ public class MmsSmsDatabase extends Database {
public static final String MMS_TRANSPORT = "mms";
public static final String SMS_TRANSPORT = "sms";
private static final String[] PROJECTION = {MmsSmsColumns.ID, MmsSmsColumns.UNIQUE_ROW_ID,
SmsDatabase.BODY, SmsDatabase.TYPE,
private static final String[] PROJECTION = {MmsSmsColumns.ID,
MmsSmsColumns.UNIQUE_ROW_ID,
SmsDatabase.BODY,
SmsDatabase.TYPE,
MmsSmsColumns.THREAD_ID,
SmsDatabase.RECIPIENT_ID, SmsDatabase.ADDRESS_DEVICE_ID, SmsDatabase.SUBJECT,
SmsDatabase.RECIPIENT_ID,
SmsDatabase.ADDRESS_DEVICE_ID,
SmsDatabase.SUBJECT,
MmsSmsColumns.NORMALIZED_DATE_SENT,
MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX,
MmsSmsColumns.DATE_SERVER,
MmsDatabase.MESSAGE_TYPE,
MmsDatabase.MESSAGE_BOX,
SmsDatabase.STATUS,
MmsSmsColumns.UNIDENTIFIED,
MmsSmsColumns.REACTIONS,
MmsDatabase.PART_COUNT,
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY,
MmsDatabase.CONTENT_LOCATION,
MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE,
MmsDatabase.EXPIRY,
MmsDatabase.STATUS,
MmsSmsColumns.DELIVERY_RECEIPT_COUNT,
MmsSmsColumns.READ_RECEIPT_COUNT,
@ -386,7 +394,8 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.VIEW_ONCE,
MmsDatabase.REACTIONS,
MmsSmsColumns.REACTIONS_UNREAD,
MmsSmsColumns.REACTIONS_LAST_SEEN};
MmsSmsColumns.REACTIONS_LAST_SEEN,
MmsSmsColumns.DATE_SERVER };
String[] smsProjection = {SmsDatabase.DATE_SENT + " AS " + MmsSmsColumns.NORMALIZED_DATE_SENT,
SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
@ -416,7 +425,8 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.VIEW_ONCE,
MmsDatabase.REACTIONS,
MmsSmsColumns.REACTIONS_UNREAD,
MmsSmsColumns.REACTIONS_LAST_SEEN};
MmsSmsColumns.REACTIONS_LAST_SEEN,
MmsSmsColumns.DATE_SERVER };
SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
@ -447,6 +457,7 @@ public class MmsSmsDatabase extends Database {
mmsColumnsPresent.add(MmsDatabase.MESSAGE_BOX);
mmsColumnsPresent.add(MmsDatabase.DATE_SENT);
mmsColumnsPresent.add(MmsDatabase.DATE_RECEIVED);
mmsColumnsPresent.add(MmsDatabase.DATE_SERVER);
mmsColumnsPresent.add(MmsDatabase.PART_COUNT);
mmsColumnsPresent.add(MmsDatabase.CONTENT_LOCATION);
mmsColumnsPresent.add(MmsDatabase.TRANSACTION_ID);
@ -486,6 +497,7 @@ public class MmsSmsDatabase extends Database {
smsColumnsPresent.add(SmsDatabase.SUBJECT);
smsColumnsPresent.add(SmsDatabase.DATE_SENT);
smsColumnsPresent.add(SmsDatabase.DATE_RECEIVED);
smsColumnsPresent.add(SmsDatabase.DATE_SERVER);
smsColumnsPresent.add(SmsDatabase.STATUS);
smsColumnsPresent.add(SmsDatabase.UNIDENTIFIED);
smsColumnsPresent.add(SmsDatabase.REACTIONS);

View file

@ -84,6 +84,7 @@ public class SmsDatabase extends MessagingDatabase {
PERSON + " INTEGER, " +
DATE_RECEIVED + " INTEGER, " +
DATE_SENT + " INTEGER, " +
DATE_SERVER + " INTEGER DEFAULT -1, " +
PROTOCOL + " INTEGER, " +
READ + " INTEGER DEFAULT 0, " +
STATUS + " INTEGER DEFAULT -1," +
@ -110,6 +111,7 @@ public class SmsDatabase extends MessagingDatabase {
"CREATE INDEX IF NOT EXISTS sms_read_and_notified_and_thread_id_index ON " + TABLE_NAME + "(" + READ + "," + NOTIFIED + "," + THREAD_ID + ");",
"CREATE INDEX IF NOT EXISTS sms_type_index ON " + TABLE_NAME + " (" + TYPE + ");",
"CREATE INDEX IF NOT EXISTS sms_date_sent_index ON " + TABLE_NAME + " (" + DATE_SENT + ");",
"CREATE INDEX IF NOT EXISTS sms_date_server_index ON " + TABLE_NAME + " (" + DATE_SERVER + ");",
"CREATE INDEX IF NOT EXISTS sms_thread_date_index ON " + TABLE_NAME + " (" + THREAD_ID + ", " + DATE_RECEIVED + ");",
"CREATE INDEX IF NOT EXISTS sms_reactions_unread_index ON " + TABLE_NAME + " (" + REACTIONS_UNREAD + ");"
};
@ -118,6 +120,7 @@ public class SmsDatabase extends MessagingDatabase {
ID, THREAD_ID, RECIPIENT_ID, ADDRESS_DEVICE_ID, PERSON,
DATE_RECEIVED + " AS " + NORMALIZED_DATE_RECEIVED,
DATE_SENT + " AS " + NORMALIZED_DATE_SENT,
DATE_SERVER,
PROTOCOL, READ, STATUS, TYPE,
REPLY_PATH_PRESENT, SUBJECT, BODY, SERVICE_CENTER, DELIVERY_RECEIPT_COUNT,
MISMATCHED_IDENTITIES, SUBSCRIPTION_ID, EXPIRES_IN, EXPIRE_STARTED,
@ -534,36 +537,6 @@ public class SmsDatabase extends MessagingDatabase {
return new Pair<>(messageId, threadId);
}
public Pair<Long, Long> copyMessageInbox(long messageId) {
try {
SmsMessageRecord record = getMessage(messageId);
ContentValues contentValues = new ContentValues();
contentValues.put(TYPE, (record.getType() & ~Types.BASE_TYPE_MASK) | Types.BASE_INBOX_TYPE);
contentValues.put(RECIPIENT_ID, record.getIndividualRecipient().getId().serialize());
contentValues.put(ADDRESS_DEVICE_ID, record.getRecipientDeviceId());
contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
contentValues.put(DATE_SENT, record.getDateSent());
contentValues.put(PROTOCOL, 31337);
contentValues.put(READ, 0);
contentValues.put(BODY, record.getBody());
contentValues.put(THREAD_ID, record.getThreadId());
contentValues.put(EXPIRES_IN, record.getExpiresIn());
SQLiteDatabase db = databaseHelper.getWritableDatabase();
long newMessageId = db.insert(TABLE_NAME, null, contentValues);
DatabaseFactory.getThreadDatabase(context).update(record.getThreadId(), true);
notifyConversationListeners(record.getThreadId());
ApplicationDependencies.getJobManager().add(new TrimThreadJob(record.getThreadId()));
return new Pair<>(newMessageId, record.getThreadId());
} catch (NoSuchMessageException e) {
throw new AssertionError(e);
}
}
boolean hasReceivedAnyCallsSince(long threadId, long timestamp) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String[] projection = new String[]{SmsDatabase.TYPE};
@ -665,6 +638,7 @@ public class SmsDatabase extends MessagingDatabase {
values.put(ADDRESS_DEVICE_ID, message.getSenderDeviceId());
values.put(DATE_RECEIVED, System.currentTimeMillis());
values.put(DATE_SENT, message.getSentTimestampMillis());
values.put(DATE_SERVER, message.getServerTimestampMillis());
values.put(PROTOCOL, message.getProtocol());
values.put(READ, unread ? 0 : 1);
values.put(SUBSCRIPTION_ID, message.getSubscriptionId());
@ -908,7 +882,7 @@ public class SmsDatabase extends MessagingDatabase {
return new OutgoingMessageReader(message, threadId);
}
public class OutgoingMessageReader {
public static class OutgoingMessageReader {
private final OutgoingTextMessage message;
private final long id;
@ -921,13 +895,25 @@ public class SmsDatabase extends MessagingDatabase {
}
public MessageRecord getCurrent() {
return new SmsMessageRecord(id, message.getMessageBody(),
message.getRecipient(), message.getRecipient(),
1, System.currentTimeMillis(), System.currentTimeMillis(),
0, message.isSecureMessage() ? MmsSmsColumns.Types.getOutgoingEncryptedMessageType() : MmsSmsColumns.Types.getOutgoingSmsMessageType(),
threadId, 0, new LinkedList<IdentityKeyMismatch>(),
message.getSubscriptionId(), message.getExpiresIn(),
System.currentTimeMillis(), 0, false, Collections.emptyList());
return new SmsMessageRecord(id,
message.getMessageBody(),
message.getRecipient(),
message.getRecipient(),
1,
System.currentTimeMillis(),
System.currentTimeMillis(),
-1,
0,
message.isSecureMessage() ? MmsSmsColumns.Types.getOutgoingEncryptedMessageType() : MmsSmsColumns.Types.getOutgoingSmsMessageType(),
threadId,
0,
new LinkedList<>(),
message.getSubscriptionId(),
message.getExpiresIn(),
System.currentTimeMillis(),
0,
false,
Collections.emptyList());
}
}
@ -952,21 +938,22 @@ public class SmsDatabase extends MessagingDatabase {
}
public SmsMessageRecord getCurrent() {
long messageId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.ID ));
long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.RECIPIENT_ID ));
int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS_DEVICE_ID ));
long type = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.TYPE ));
long messageId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.ID));
long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.RECIPIENT_ID));
int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS_DEVICE_ID));
long type = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.TYPE));
long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_RECEIVED));
long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_SENT ));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.THREAD_ID ));
int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS ));
long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_SENT));
long dateServer = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.DATE_SERVER));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.THREAD_ID));
int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS));
int deliveryReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.DELIVERY_RECEIPT_COUNT));
int readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.READ_RECEIPT_COUNT ));
int readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.READ_RECEIPT_COUNT));
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.MISMATCHED_IDENTITIES));
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.SUBSCRIPTION_ID ));
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRES_IN ));
long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRE_STARTED ));
String body = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.BODY ));
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.SUBSCRIPTION_ID));
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRES_IN));
long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRE_STARTED));
String body = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.BODY));
boolean unidentified = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.UNIDENTIFIED)) == 1;
List<ReactionRecord> reactions = parseReactions(cursor);
@ -980,7 +967,7 @@ public class SmsDatabase extends MessagingDatabase {
return new SmsMessageRecord(messageId, body, recipient,
recipient,
addressDeviceId,
dateSent, dateReceived, deliveryReceiptCount, type,
dateSent, dateReceived, dateServer, deliveryReceiptCount, type,
threadId, status, mismatches, subscriptionId,
expiresIn, expireStarted,
readReceiptCount, unidentified, reactions);

View file

@ -128,8 +128,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int ATTACHMENT_UPLOAD_TIMESTAMP = 56;
private static final int ATTACHMENT_CDN_NUMBER = 57;
private static final int JOB_INPUT_DATA = 58;
private static final int SERVER_TIMESTAMP = 59;
private static final int DATABASE_VERSION = 58;
private static final int DATABASE_VERSION = 59;
private static final String DATABASE_NAME = "signal.db";
private final Context context;
@ -873,6 +874,14 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE job_spec ADD COLUMN serialized_input_data TEXT DEFAULT NULL");
}
if (oldVersion < SERVER_TIMESTAMP) {
db.execSQL("ALTER TABLE sms ADD COLUMN date_server INTEGER DEFAULT -1");
db.execSQL("CREATE INDEX IF NOT EXISTS sms_date_server_index ON sms (date_server)");
db.execSQL("ALTER TABLE mms ADD COLUMN date_server INTEGER DEFAULT -1");
db.execSQL("CREATE INDEX IF NOT EXISTS mms_date_server_index ON mms (date_server)");
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();

View file

@ -46,22 +46,34 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
private final int partCount;
public MediaMmsMessageRecord(long id, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId,
long dateSent, long dateReceived, int deliveryReceiptCount,
long threadId, String body,
public MediaMmsMessageRecord(long id,
Recipient conversationRecipient,
Recipient individualRecipient,
int recipientDeviceId,
long dateSent,
long dateReceived,
long dateServer,
int deliveryReceiptCount,
long threadId,
String body,
@NonNull SlideDeck slideDeck,
int partCount, long mailbox,
int partCount,
long mailbox,
List<IdentityKeyMismatch> mismatches,
List<NetworkFailure> failures, int subscriptionId,
long expiresIn, long expireStarted,
boolean viewOnce, int readReceiptCount,
@Nullable Quote quote, @NonNull List<Contact> contacts,
@NonNull List<LinkPreview> linkPreviews, boolean unidentified,
List<NetworkFailure> failures,
int subscriptionId,
long expiresIn,
long expireStarted,
boolean viewOnce,
int readReceiptCount,
@Nullable Quote quote,
@NonNull List<Contact> contacts,
@NonNull List<LinkPreview> linkPreviews,
boolean unidentified,
@NonNull List<ReactionRecord> reactions)
{
super(id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent,
dateReceived, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox, mismatches, failures,
dateReceived, dateServer, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox, mismatches, failures,
subscriptionId, expiresIn, expireStarted, viewOnce, slideDeck,
readReceiptCount, quote, contacts, linkPreviews, unidentified, reactions);
this.partCount = partCount;

View file

@ -54,10 +54,11 @@ public abstract class MessageRecord extends DisplayRecord {
private final long expireStarted;
private final boolean unidentified;
private final List<ReactionRecord> reactions;
private final long serverTimestamp;
MessageRecord(long id, String body, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId,
long dateSent, long dateReceived, long threadId,
long dateSent, long dateReceived, long dateServer, long threadId,
int deliveryStatus, int deliveryReceiptCount, long type,
List<IdentityKeyMismatch> mismatches,
List<NetworkFailure> networkFailures,
@ -77,6 +78,7 @@ public abstract class MessageRecord extends DisplayRecord {
this.expireStarted = expireStarted;
this.unidentified = unidentified;
this.reactions = reactions;
this.serverTimestamp = dateServer;
}
public abstract boolean isMms();
@ -145,6 +147,10 @@ public abstract class MessageRecord extends DisplayRecord {
return getDateReceived();
}
public long getServerTimestamp() {
return serverTimestamp;
}
public boolean isForcedSms() {
return SmsDatabase.Types.isForcedSms(type);
}

View file

@ -26,7 +26,7 @@ public abstract class MmsMessageRecord extends MessageRecord {
MmsMessageRecord(long id, String body, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId, long dateSent,
long dateReceived, long threadId, int deliveryStatus, int deliveryReceiptCount,
long dateReceived, long dateServer, long threadId, int deliveryStatus, int deliveryReceiptCount,
long type, List<IdentityKeyMismatch> mismatches,
List<NetworkFailure> networkFailures, int subscriptionId, long expiresIn,
long expireStarted, boolean viewOnce,
@ -35,7 +35,7 @@ public abstract class MmsMessageRecord extends MessageRecord {
@NonNull List<LinkPreview> linkPreviews, boolean unidentified,
@NonNull List<ReactionRecord> reactions)
{
super(id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent, dateReceived, threadId, deliveryStatus, deliveryReceiptCount, type, mismatches, networkFailures, subscriptionId, expiresIn, expireStarted, readReceiptCount, unidentified, reactions);
super(id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent, dateReceived, dateServer, threadId, deliveryStatus, deliveryReceiptCount, type, mismatches, networkFailures, subscriptionId, expiresIn, expireStarted, readReceiptCount, unidentified, reactions);
this.slideDeck = slideDeck;
this.quote = quote;

View file

@ -55,8 +55,8 @@ public class NotificationMmsMessageRecord extends MmsMessageRecord {
int subscriptionId, SlideDeck slideDeck, int readReceiptCount)
{
super(id, "", conversationRecipient, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox,
new LinkedList<IdentityKeyMismatch>(), new LinkedList<NetworkFailure>(), subscriptionId,
dateSent, dateReceived, -1, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox,
new LinkedList<>(), new LinkedList<>(), subscriptionId,
0, 0, false, slideDeck, readReceiptCount, null, Collections.emptyList(), Collections.emptyList(), false,
Collections.emptyList());

View file

@ -43,7 +43,7 @@ public class SmsMessageRecord extends MessageRecord {
String body, Recipient recipient,
Recipient individualRecipient,
int recipientDeviceId,
long dateSent, long dateReceived,
long dateSent, long dateReceived, long dateServer,
int deliveryReceiptCount,
long type, long threadId,
int status, List<IdentityKeyMismatch> mismatches,
@ -52,7 +52,7 @@ public class SmsMessageRecord extends MessageRecord {
@NonNull List<ReactionRecord> reactions)
{
super(id, body, recipient, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, status, deliveryReceiptCount, type,
dateSent, dateReceived, dateServer, threadId, status, deliveryReceiptCount, type,
mismatches, new LinkedList<>(), subscriptionId,
expiresIn, expireStarted, readReceiptCount, unidentified, reactions);
}

View file

@ -246,7 +246,7 @@ public final class GroupV1MessageProcessor {
} else {
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
String body = Base64.encodeBytes(storage.toByteArray());
IncomingTextMessage incoming = new IncomingTextMessage(Recipient.externalPush(context, content.getSender()).getId(), content.getSenderDevice(), content.getTimestamp(), body, Optional.of(GroupId.v1(group.getGroupId())), 0, content.isNeedsReceipt());
IncomingTextMessage incoming = new IncomingTextMessage(Recipient.externalPush(context, content.getSender()).getId(), content.getSenderDevice(), content.getTimestamp(), content.getServerTimestamp(), body, Optional.of(GroupId.v1(group.getGroupId())), 0, content.isNeedsReceipt());
IncomingGroupMessage groupMessage = new IncomingGroupMessage(incoming, storage, body);
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);

View file

@ -235,7 +235,7 @@ public class MmsDownloadJob extends BaseJob {
group = Optional.of(DatabaseFactory.getGroupDatabase(context).getOrCreateMmsGroupForMembers(recipients));
}
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false, false, false);
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, -1, attachments, subscriptionId, 0, false, false, false);
Optional<InsertResult> insertResult = database.insertMessageInbox(message, contentLocation, threadId);
if (insertResult.isPresent()) {

View file

@ -482,6 +482,7 @@ public final class PushProcessMessageJob extends BaseJob {
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Recipient.externalPush(context, content.getSender()).getId(),
content.getSenderDevice(),
content.getTimestamp(),
content.getServerTimestamp(),
"", Optional.absent(), 0,
content.isNeedsReceipt());
@ -572,8 +573,11 @@ public final class PushProcessMessageJob extends BaseJob {
Recipient sender = Recipient.externalPush(context, content.getSender());
Recipient recipient = getMessageDestination(content, message);
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(sender.getId(),
message.getTimestamp(), -1,
message.getExpiresInSeconds() * 1000L, true,
message.getTimestamp(),
content.getServerTimestamp(),
-1,
message.getExpiresInSeconds() * 1000L,
true,
false,
content.isNeedsReceipt(),
Optional.absent(),
@ -859,8 +863,11 @@ public final class PushProcessMessageJob extends BaseJob {
Optional<List<LinkPreview>> linkPreviews = getLinkPreviews(message.getPreviews(), message.getBody().or(""));
Optional<Attachment> sticker = getStickerAttachment(message.getSticker());
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(Recipient.externalPush(context, content.getSender()).getId(),
message.getTimestamp(), -1,
message.getExpiresInSeconds() * 1000L, false,
message.getTimestamp(),
content.getServerTimestamp(),
-1,
message.getExpiresInSeconds() * 1000L,
false,
message.isViewOnce(),
content.isNeedsReceipt(),
message.getBody(),
@ -1071,7 +1078,9 @@ public final class PushProcessMessageJob extends BaseJob {
IncomingTextMessage textMessage = new IncomingTextMessage(Recipient.externalPush(context, content.getSender()).getId(),
content.getSenderDevice(),
message.getTimestamp(), body,
message.getTimestamp(),
content.getServerTimestamp(),
body,
groupId,
message.getExpiresInSeconds() * 1000L,
content.isNeedsReceipt());
@ -1498,7 +1507,7 @@ public final class PushProcessMessageJob extends BaseJob {
private Optional<InsertResult> insertPlaceholder(@NonNull String sender, int senderDevice, long timestamp, Optional<GroupId> groupId) {
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
IncomingTextMessage textMessage = new IncomingTextMessage(Recipient.external(context, sender).getId(),
senderDevice, timestamp, "",
senderDevice, timestamp, -1, "",
groupId, 0, false);
textMessage = new IncomingEncryptedMessage(textMessage, "");

View file

@ -24,6 +24,7 @@ public class IncomingMediaMessage {
private final String body;
private final boolean push;
private final long sentTimeMillis;
private final long serverTimeMillis;
private final int subscriptionId;
private final long expiresIn;
private final boolean expirationUpdate;
@ -39,6 +40,7 @@ public class IncomingMediaMessage {
Optional<GroupId> groupId,
String body,
long sentTimeMillis,
long serverTimeMillis,
List<Attachment> attachments,
int subscriptionId,
long expiresIn,
@ -49,6 +51,7 @@ public class IncomingMediaMessage {
this.from = from;
this.groupId = groupId.orNull();
this.sentTimeMillis = sentTimeMillis;
this.serverTimeMillis = serverTimeMillis;
this.body = body;
this.push = false;
this.subscriptionId = subscriptionId;
@ -63,6 +66,7 @@ public class IncomingMediaMessage {
public IncomingMediaMessage(@NonNull RecipientId from,
long sentTimeMillis,
long serverTimeMillis,
int subscriptionId,
long expiresIn,
boolean expirationUpdate,
@ -79,6 +83,7 @@ public class IncomingMediaMessage {
this.push = true;
this.from = from;
this.sentTimeMillis = sentTimeMillis;
this.serverTimeMillis = serverTimeMillis;
this.body = body.orNull();
this.subscriptionId = subscriptionId;
this.expiresIn = expiresIn;
@ -131,6 +136,10 @@ public class IncomingMediaMessage {
return sentTimeMillis;
}
public long getServerTimeMillis() {
return serverTimeMillis;
}
public long getExpiresIn() {
return expiresIn;
}

View file

@ -6,7 +6,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
public class IncomingJoinedMessage extends IncomingTextMessage {
public IncomingJoinedMessage(RecipientId sender) {
super(sender, 1, System.currentTimeMillis(), null, Optional.absent(), 0, false);
super(sender, 1, System.currentTimeMillis(), -1, null, Optional.absent(), 0, false);
}
@Override

View file

@ -37,6 +37,7 @@ public class IncomingTextMessage implements Parcelable {
private final boolean replyPathPresent;
private final String pseudoSubject;
private final long sentTimestampMillis;
private final long serverTimestampMillis;
@Nullable private final GroupId groupId;
private final boolean push;
private final int subscriptionId;
@ -44,70 +45,79 @@ public class IncomingTextMessage implements Parcelable {
private final boolean unidentified;
public IncomingTextMessage(@NonNull RecipientId sender, @NonNull SmsMessage message, int subscriptionId) {
this.message = message.getDisplayMessageBody();
this.sender = sender;
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
this.protocol = message.getProtocolIdentifier();
this.serviceCenterAddress = message.getServiceCenterAddress();
this.replyPathPresent = message.isReplyPathPresent();
this.pseudoSubject = message.getPseudoSubject();
this.sentTimestampMillis = message.getTimestampMillis();
this.subscriptionId = subscriptionId;
this.expiresInMillis = 0;
this.groupId = null;
this.push = false;
this.unidentified = false;
this.message = message.getDisplayMessageBody();
this.sender = sender;
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
this.protocol = message.getProtocolIdentifier();
this.serviceCenterAddress = message.getServiceCenterAddress();
this.replyPathPresent = message.isReplyPathPresent();
this.pseudoSubject = message.getPseudoSubject();
this.sentTimestampMillis = message.getTimestampMillis();
this.serverTimestampMillis = -1;
this.subscriptionId = subscriptionId;
this.expiresInMillis = 0;
this.groupId = null;
this.push = false;
this.unidentified = false;
}
public IncomingTextMessage(@NonNull RecipientId sender, int senderDeviceId, long sentTimestampMillis,
String encodedBody, Optional<GroupId> groupId,
long expiresInMillis, boolean unidentified)
public IncomingTextMessage(@NonNull RecipientId sender,
int senderDeviceId,
long sentTimestampMillis,
long serverTimestampMillis,
String encodedBody,
Optional<GroupId> groupId,
long expiresInMillis,
boolean unidentified)
{
this.message = encodedBody;
this.sender = sender;
this.senderDeviceId = senderDeviceId;
this.protocol = 31337;
this.serviceCenterAddress = "GCM";
this.replyPathPresent = true;
this.pseudoSubject = "";
this.sentTimestampMillis = sentTimestampMillis;
this.push = true;
this.subscriptionId = -1;
this.expiresInMillis = expiresInMillis;
this.unidentified = unidentified;
this.groupId = groupId.orNull();
this.message = encodedBody;
this.sender = sender;
this.senderDeviceId = senderDeviceId;
this.protocol = 31337;
this.serviceCenterAddress = "GCM";
this.replyPathPresent = true;
this.pseudoSubject = "";
this.sentTimestampMillis = sentTimestampMillis;
this.serverTimestampMillis = serverTimestampMillis;
this.push = true;
this.subscriptionId = -1;
this.expiresInMillis = expiresInMillis;
this.unidentified = unidentified;
this.groupId = groupId.orNull();
}
public IncomingTextMessage(Parcel in) {
this.message = in.readString();
this.sender = in.readParcelable(IncomingTextMessage.class.getClassLoader());
this.senderDeviceId = in.readInt();
this.protocol = in.readInt();
this.serviceCenterAddress = in.readString();
this.replyPathPresent = (in.readInt() == 1);
this.pseudoSubject = in.readString();
this.sentTimestampMillis = in.readLong();
this.groupId = GroupId.parseNullable(in.readString());
this.push = (in.readInt() == 1);
this.subscriptionId = in.readInt();
this.expiresInMillis = in.readLong();
this.unidentified = in.readInt() == 1;
this.message = in.readString();
this.sender = in.readParcelable(IncomingTextMessage.class.getClassLoader());
this.senderDeviceId = in.readInt();
this.protocol = in.readInt();
this.serviceCenterAddress = in.readString();
this.replyPathPresent = (in.readInt() == 1);
this.pseudoSubject = in.readString();
this.sentTimestampMillis = in.readLong();
this.serverTimestampMillis = in.readLong();
this.groupId = GroupId.parseNullable(in.readString());
this.push = (in.readInt() == 1);
this.subscriptionId = in.readInt();
this.expiresInMillis = in.readLong();
this.unidentified = in.readInt() == 1;
}
public IncomingTextMessage(IncomingTextMessage base, String newBody) {
this.message = newBody;
this.sender = base.getSender();
this.senderDeviceId = base.getSenderDeviceId();
this.protocol = base.getProtocol();
this.serviceCenterAddress = base.getServiceCenterAddress();
this.replyPathPresent = base.isReplyPathPresent();
this.pseudoSubject = base.getPseudoSubject();
this.sentTimestampMillis = base.getSentTimestampMillis();
this.groupId = base.getGroupId();
this.push = base.isPush();
this.subscriptionId = base.getSubscriptionId();
this.expiresInMillis = base.getExpiresIn();
this.unidentified = base.isUnidentified();
this.message = newBody;
this.sender = base.getSender();
this.senderDeviceId = base.getSenderDeviceId();
this.protocol = base.getProtocol();
this.serviceCenterAddress = base.getServiceCenterAddress();
this.replyPathPresent = base.isReplyPathPresent();
this.pseudoSubject = base.getPseudoSubject();
this.sentTimestampMillis = base.getSentTimestampMillis();
this.serverTimestampMillis = base.getServerTimestampMillis();
this.groupId = base.getGroupId();
this.push = base.isPush();
this.subscriptionId = base.getSubscriptionId();
this.expiresInMillis = base.getExpiresIn();
this.unidentified = base.isUnidentified();
}
public IncomingTextMessage(List<IncomingTextMessage> fragments) {
@ -117,36 +127,38 @@ public class IncomingTextMessage implements Parcelable {
body.append(message.getMessageBody());
}
this.message = body.toString();
this.sender = fragments.get(0).getSender();
this.senderDeviceId = fragments.get(0).getSenderDeviceId();
this.protocol = fragments.get(0).getProtocol();
this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress();
this.replyPathPresent = fragments.get(0).isReplyPathPresent();
this.pseudoSubject = fragments.get(0).getPseudoSubject();
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
this.groupId = fragments.get(0).getGroupId();
this.push = fragments.get(0).isPush();
this.subscriptionId = fragments.get(0).getSubscriptionId();
this.expiresInMillis = fragments.get(0).getExpiresIn();
this.unidentified = fragments.get(0).isUnidentified();
this.message = body.toString();
this.sender = fragments.get(0).getSender();
this.senderDeviceId = fragments.get(0).getSenderDeviceId();
this.protocol = fragments.get(0).getProtocol();
this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress();
this.replyPathPresent = fragments.get(0).isReplyPathPresent();
this.pseudoSubject = fragments.get(0).getPseudoSubject();
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
this.serverTimestampMillis = fragments.get(0).getServerTimestampMillis();
this.groupId = fragments.get(0).getGroupId();
this.push = fragments.get(0).isPush();
this.subscriptionId = fragments.get(0).getSubscriptionId();
this.expiresInMillis = fragments.get(0).getExpiresIn();
this.unidentified = fragments.get(0).isUnidentified();
}
protected IncomingTextMessage(@NonNull RecipientId sender, @Nullable GroupId groupId)
{
this.message = "";
this.sender = sender;
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
this.protocol = 31338;
this.serviceCenterAddress = "Outgoing";
this.replyPathPresent = true;
this.pseudoSubject = "";
this.sentTimestampMillis = System.currentTimeMillis();
this.groupId = groupId;
this.push = true;
this.subscriptionId = -1;
this.expiresInMillis = 0;
this.unidentified = false;
this.message = "";
this.sender = sender;
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
this.protocol = 31338;
this.serviceCenterAddress = "Outgoing";
this.replyPathPresent = true;
this.pseudoSubject = "";
this.sentTimestampMillis = System.currentTimeMillis();
this.serverTimestampMillis = sentTimestampMillis;
this.groupId = groupId;
this.push = true;
this.subscriptionId = -1;
this.expiresInMillis = 0;
this.unidentified = false;
}
public int getSubscriptionId() {
@ -161,6 +173,10 @@ public class IncomingTextMessage implements Parcelable {
return sentTimestampMillis;
}
public long getServerTimestampMillis() {
return serverTimestampMillis;
}
public String getPseudoSubject() {
return pseudoSubject;
}

View file

@ -78,7 +78,7 @@ public class IdentityUtil {
if (groupRecord.getMembers().contains(recipient.getId()) && groupRecord.isActive() && !groupRecord.isMms()) {
if (remote) {
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, null, Optional.of(groupRecord.getId()), 0, false);
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, null, Optional.of(groupRecord.getId()), 0, false);
if (verified) incoming = new IncomingIdentityVerifiedMessage(incoming);
else incoming = new IncomingIdentityDefaultMessage(incoming);
@ -100,7 +100,7 @@ public class IdentityUtil {
}
if (remote) {
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, null, Optional.absent(), 0, false);
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, null, Optional.absent(), 0, false);
if (verified) incoming = new IncomingIdentityVerifiedMessage(incoming);
else incoming = new IncomingIdentityDefaultMessage(incoming);
@ -129,14 +129,14 @@ public class IdentityUtil {
while ((groupRecord = reader.getNext()) != null) {
if (groupRecord.getMembers().contains(recipient.getId()) && groupRecord.isActive()) {
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, null, Optional.of(groupRecord.getId()), 0, false);
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, time, null, Optional.of(groupRecord.getId()), 0, false);
IncomingIdentityUpdateMessage groupUpdate = new IncomingIdentityUpdateMessage(incoming);
smsDatabase.insertMessageInbox(groupUpdate);
}
}
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, null, Optional.absent(), 0, false);
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, null, Optional.absent(), 0, false);
IncomingIdentityUpdateMessage individualUpdate = new IncomingIdentityUpdateMessage(incoming);
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(individualUpdate);

View file

@ -176,14 +176,14 @@ public class SignalServiceCipher {
SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);
paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext));
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), false);
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerTimestamp(), false);
sessionVersion = sessionCipher.getSessionVersion();
} else if (envelope.isSignalMessage()) {
SignalProtocolAddress sourceAddress = getPreferredProtocolAddress(signalProtocolStore, envelope.getSourceAddress(), envelope.getSourceDevice());
SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);
paddedMessage = sessionCipher.decrypt(new SignalMessage(ciphertext));
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), false);
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerTimestamp(), false);
sessionVersion = sessionCipher.getSessionVersion();
} else if (envelope.isUnidentifiedSender()) {
SealedSessionCipher sealedSessionCipher = new SealedSessionCipher(signalProtocolStore, localAddress.getUuid().orNull(), localAddress.getNumber().orNull(), 1);
@ -192,7 +192,7 @@ public class SignalServiceCipher {
SignalProtocolAddress protocolAddress = getPreferredProtocolAddress(signalProtocolStore, resultAddress, result.getDeviceId());
paddedMessage = result.getPaddedMessage();
metadata = new SignalServiceMetadata(resultAddress, result.getDeviceId(), envelope.getTimestamp(), true);
metadata = new SignalServiceMetadata(resultAddress, result.getDeviceId(), envelope.getTimestamp(), envelope.getServerTimestamp(), true);
sessionVersion = sealedSessionCipher.getSessionVersion(protocolAddress);
} else {
throw new InvalidMetadataMessageException("Unknown type: " + envelope.getType());

View file

@ -58,6 +58,7 @@ public final class SignalServiceContent {
private final SignalServiceAddress sender;
private final int senderDevice;
private final long timestamp;
private final long serverTimestamp;
private final boolean needsReceipt;
private final SignalServiceContentProto serializedState;
@ -67,10 +68,11 @@ public final class SignalServiceContent {
private final Optional<SignalServiceReceiptMessage> readMessage;
private final Optional<SignalServiceTypingMessage> typingMessage;
private SignalServiceContent(SignalServiceDataMessage message, SignalServiceAddress sender, int senderDevice, long timestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
private SignalServiceContent(SignalServiceDataMessage message, SignalServiceAddress sender, int senderDevice, long timestamp, long serverTimestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
this.sender = sender;
this.senderDevice = senderDevice;
this.timestamp = timestamp;
this.serverTimestamp = serverTimestamp;
this.needsReceipt = needsReceipt;
this.serializedState = serializedState;
@ -81,10 +83,11 @@ public final class SignalServiceContent {
this.typingMessage = Optional.absent();
}
private SignalServiceContent(SignalServiceSyncMessage synchronizeMessage, SignalServiceAddress sender, int senderDevice, long timestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
private SignalServiceContent(SignalServiceSyncMessage synchronizeMessage, SignalServiceAddress sender, int senderDevice, long timestamp, long serverTimestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
this.sender = sender;
this.senderDevice = senderDevice;
this.timestamp = timestamp;
this.serverTimestamp = serverTimestamp;
this.needsReceipt = needsReceipt;
this.serializedState = serializedState;
@ -95,10 +98,11 @@ public final class SignalServiceContent {
this.typingMessage = Optional.absent();
}
private SignalServiceContent(SignalServiceCallMessage callMessage, SignalServiceAddress sender, int senderDevice, long timestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
private SignalServiceContent(SignalServiceCallMessage callMessage, SignalServiceAddress sender, int senderDevice, long timestamp, long serverTimestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
this.sender = sender;
this.senderDevice = senderDevice;
this.timestamp = timestamp;
this.serverTimestamp = serverTimestamp;
this.needsReceipt = needsReceipt;
this.serializedState = serializedState;
@ -109,10 +113,11 @@ public final class SignalServiceContent {
this.typingMessage = Optional.absent();
}
private SignalServiceContent(SignalServiceReceiptMessage receiptMessage, SignalServiceAddress sender, int senderDevice, long timestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
private SignalServiceContent(SignalServiceReceiptMessage receiptMessage, SignalServiceAddress sender, int senderDevice, long timestamp, long serverTimestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
this.sender = sender;
this.senderDevice = senderDevice;
this.timestamp = timestamp;
this.serverTimestamp = serverTimestamp;
this.needsReceipt = needsReceipt;
this.serializedState = serializedState;
@ -123,10 +128,11 @@ public final class SignalServiceContent {
this.typingMessage = Optional.absent();
}
private SignalServiceContent(SignalServiceTypingMessage typingMessage, SignalServiceAddress sender, int senderDevice, long timestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
private SignalServiceContent(SignalServiceTypingMessage typingMessage, SignalServiceAddress sender, int senderDevice, long timestamp, long serverTimestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
this.sender = sender;
this.senderDevice = senderDevice;
this.timestamp = timestamp;
this.serverTimestamp = serverTimestamp;
this.needsReceipt = needsReceipt;
this.serializedState = serializedState;
@ -169,6 +175,10 @@ public final class SignalServiceContent {
return timestamp;
}
public long getServerTimestamp() {
return serverTimestamp;
}
public boolean isNeedsReceipt() {
return needsReceipt;
}
@ -206,6 +216,7 @@ public final class SignalServiceContent {
metadata.getSender(),
metadata.getSenderDevice(),
metadata.getTimestamp(),
metadata.getServerTimestamp(),
metadata.isNeedsReceipt(),
serviceContentProto);
} else if (serviceContentProto.getDataCase() == SignalServiceContentProto.DataCase.CONTENT) {
@ -216,6 +227,7 @@ public final class SignalServiceContent {
metadata.getSender(),
metadata.getSenderDevice(),
metadata.getTimestamp(),
metadata.getServerTimestamp(),
metadata.isNeedsReceipt(),
serviceContentProto);
} else if (message.hasSyncMessage() && localAddress.matches(metadata.getSender())) {
@ -223,6 +235,7 @@ public final class SignalServiceContent {
metadata.getSender(),
metadata.getSenderDevice(),
metadata.getTimestamp(),
metadata.getServerTimestamp(),
metadata.isNeedsReceipt(),
serviceContentProto);
} else if (message.hasCallMessage()) {
@ -230,6 +243,7 @@ public final class SignalServiceContent {
metadata.getSender(),
metadata.getSenderDevice(),
metadata.getTimestamp(),
metadata.getServerTimestamp(),
metadata.isNeedsReceipt(),
serviceContentProto);
} else if (message.hasReceiptMessage()) {
@ -237,6 +251,7 @@ public final class SignalServiceContent {
metadata.getSender(),
metadata.getSenderDevice(),
metadata.getTimestamp(),
metadata.getServerTimestamp(),
metadata.isNeedsReceipt(),
serviceContentProto);
} else if (message.hasTypingMessage()) {
@ -244,6 +259,7 @@ public final class SignalServiceContent {
metadata.getSender(),
metadata.getSenderDevice(),
metadata.getTimestamp(),
metadata.getServerTimestamp(),
false,
serviceContentProto);
}

View file

@ -6,13 +6,15 @@ public final class SignalServiceMetadata {
private final SignalServiceAddress sender;
private final int senderDevice;
private final long timestamp;
private final long serverTimestamp;
private final boolean needsReceipt;
public SignalServiceMetadata(SignalServiceAddress sender, int senderDevice, long timestamp, boolean needsReceipt) {
this.sender = sender;
this.senderDevice = senderDevice;
this.timestamp = timestamp;
this.needsReceipt = needsReceipt;
public SignalServiceMetadata(SignalServiceAddress sender, int senderDevice, long timestamp, long serverTimestamp, boolean needsReceipt) {
this.sender = sender;
this.senderDevice = senderDevice;
this.timestamp = timestamp;
this.serverTimestamp = serverTimestamp;
this.needsReceipt = needsReceipt;
}
public SignalServiceAddress getSender() {
@ -27,6 +29,10 @@ public final class SignalServiceMetadata {
return timestamp;
}
public long getServerTimestamp() {
return serverTimestamp;
}
public boolean isNeedsReceipt() {
return needsReceipt;
}

View file

@ -14,13 +14,15 @@ public final class SignalServiceMetadataProtobufSerializer {
.setSenderDevice(metadata.getSenderDevice())
.setNeedsReceipt(metadata.isNeedsReceipt())
.setTimestamp(metadata.getTimestamp())
.setServerTimestamp(metadata.getServerTimestamp())
.build();
}
public static SignalServiceMetadata fromProtobuf(MetadataProto metadata) {
return new SignalServiceMetadata(SignalServiceAddressProtobufSerializer.fromProtobuf(metadata.getAddress()),
metadata.getSenderDevice(),
metadata.getTimestamp(),
metadata.getNeedsReceipt());
metadata.getSenderDevice(),
metadata.getTimestamp(),
metadata.getServerTimestamp(),
metadata.getNeedsReceipt());
}
}

View file

@ -22,10 +22,11 @@ message SignalServiceContentProto {
}
message MetadataProto {
optional AddressProto address = 1;
optional int32 senderDevice = 2;
optional int64 timestamp = 3;
optional bool needsReceipt = 4;
optional AddressProto address = 1;
optional int32 senderDevice = 2;
optional int64 timestamp = 3;
optional int64 serverTimestamp = 5;
optional bool needsReceipt = 4;
}
message AddressProto {