mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-26 14:27:34 +00:00
Detect real age of call request by using server timestamps.
This commit is contained in:

committed by
Alan Evans

parent
891a1af995
commit
629ba105cb
@@ -175,7 +175,9 @@ public class ConfirmIdentityDialog extends AlertDialog {
|
||||
messageRecord.getDateSent(),
|
||||
legacy ? Base64.decode(messageRecord.getBody()) : null,
|
||||
!legacy ? Base64.decode(messageRecord.getBody()) : null,
|
||||
0, null);
|
||||
0,
|
||||
0,
|
||||
null);
|
||||
|
||||
long pushId = pushDatabase.insert(envelope);
|
||||
|
||||
|
@@ -3,10 +3,8 @@ package org.thoughtcrime.securesms.database;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.sqlcipher.database.SQLiteDatabase;
|
||||
|
||||
@@ -16,31 +14,38 @@ import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PushDatabase extends Database {
|
||||
|
||||
private static final String TAG = PushDatabase.class.getSimpleName();
|
||||
|
||||
private static final String TABLE_NAME = "push";
|
||||
public static final String ID = "_id";
|
||||
public static final String TYPE = "type";
|
||||
public static final String SOURCE_E164 = "source";
|
||||
public static final String SOURCE_UUID = "source_uuid";
|
||||
public static final String DEVICE_ID = "device_id";
|
||||
public static final String LEGACY_MSG = "body";
|
||||
public static final String CONTENT = "content";
|
||||
public static final String TIMESTAMP = "timestamp";
|
||||
public static final String SERVER_TIMESTAMP = "server_timestamp";
|
||||
public static final String SERVER_GUID = "server_guid";
|
||||
private static final String TABLE_NAME = "push";
|
||||
public static final String ID = "_id";
|
||||
public static final String TYPE = "type";
|
||||
public static final String SOURCE_E164 = "source";
|
||||
public static final String SOURCE_UUID = "source_uuid";
|
||||
public static final String DEVICE_ID = "device_id";
|
||||
public static final String LEGACY_MSG = "body";
|
||||
public static final String CONTENT = "content";
|
||||
public static final String TIMESTAMP = "timestamp";
|
||||
public static final String SERVER_RECEIVED_TIMESTAMP = "server_timestamp";
|
||||
public static final String SERVER_DELIVERED_TIMESTAMP = "server_delivered_timestamp";
|
||||
public static final String SERVER_GUID = "server_guid";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
TYPE + " INTEGER, " + SOURCE_E164 + " TEXT, " + SOURCE_UUID + " TEXT, " + DEVICE_ID + " INTEGER, " + LEGACY_MSG + " TEXT, " + CONTENT + " TEXT, " + TIMESTAMP + " INTEGER, " +
|
||||
SERVER_TIMESTAMP + " INTEGER DEFAULT 0, " + SERVER_GUID + " TEXT DEFAULT NULL);";
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
TYPE + " INTEGER, " +
|
||||
SOURCE_E164 + " TEXT, " +
|
||||
SOURCE_UUID + " TEXT, " +
|
||||
DEVICE_ID + " INTEGER, " +
|
||||
LEGACY_MSG + " TEXT, " +
|
||||
CONTENT + " TEXT, " +
|
||||
TIMESTAMP + " INTEGER, " +
|
||||
SERVER_RECEIVED_TIMESTAMP + " INTEGER DEFAULT 0, " +
|
||||
SERVER_DELIVERED_TIMESTAMP + " INTEGER DEFAULT 0, " +
|
||||
SERVER_GUID + " TEXT DEFAULT NULL);";
|
||||
|
||||
public PushDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
@@ -60,7 +65,8 @@ public class PushDatabase extends Database {
|
||||
values.put(LEGACY_MSG, envelope.hasLegacyMessage() ? Base64.encodeBytes(envelope.getLegacyMessage()) : "");
|
||||
values.put(CONTENT, envelope.hasContent() ? Base64.encodeBytes(envelope.getContent()) : "");
|
||||
values.put(TIMESTAMP, envelope.getTimestamp());
|
||||
values.put(SERVER_TIMESTAMP, envelope.getServerTimestamp());
|
||||
values.put(SERVER_RECEIVED_TIMESTAMP, envelope.getServerReceivedTimestamp());
|
||||
values.put(SERVER_DELIVERED_TIMESTAMP, envelope.getServerDeliveredTimestamp());
|
||||
values.put(SERVER_GUID, envelope.getUuid());
|
||||
|
||||
return databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, values);
|
||||
@@ -87,7 +93,8 @@ public class PushDatabase extends Database {
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP)),
|
||||
Util.isEmpty(legacyMessage) ? null : Base64.decode(legacyMessage),
|
||||
Util.isEmpty(content) ? null : Base64.decode(content),
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP)),
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_RECEIVED_TIMESTAMP)),
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_DELIVERED_TIMESTAMP)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -154,15 +161,16 @@ public class PushDatabase extends Database {
|
||||
if (cursor == null || !cursor.moveToNext())
|
||||
return null;
|
||||
|
||||
int type = cursor.getInt(cursor.getColumnIndexOrThrow(TYPE));
|
||||
String sourceUuid = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE_UUID));
|
||||
String sourceE164 = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE_E164));
|
||||
int deviceId = cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID));
|
||||
String legacyMessage = cursor.getString(cursor.getColumnIndexOrThrow(LEGACY_MSG));
|
||||
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
|
||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
|
||||
long serverTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP));
|
||||
String serverGuid = cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID));
|
||||
int type = cursor.getInt(cursor.getColumnIndexOrThrow(TYPE));
|
||||
String sourceUuid = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE_UUID));
|
||||
String sourceE164 = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE_E164));
|
||||
int deviceId = cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID));
|
||||
String legacyMessage = cursor.getString(cursor.getColumnIndexOrThrow(LEGACY_MSG));
|
||||
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
|
||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
|
||||
long serverReceivedTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_RECEIVED_TIMESTAMP));
|
||||
long serverDeliveredTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_DELIVERED_TIMESTAMP));
|
||||
String serverGuid = cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID));
|
||||
|
||||
return new SignalServiceEnvelope(type,
|
||||
SignalServiceAddress.fromRaw(sourceUuid, sourceE164),
|
||||
@@ -170,7 +178,8 @@ public class PushDatabase extends Database {
|
||||
timestamp,
|
||||
legacyMessage != null ? Base64.decode(legacyMessage) : null,
|
||||
content != null ? Base64.decode(content) : null,
|
||||
serverTimestamp,
|
||||
serverReceivedTimestamp,
|
||||
serverDeliveredTimestamp,
|
||||
serverGuid);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
|
@@ -136,8 +136,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int COLOR_MIGRATION = 61;
|
||||
private static final int LAST_SCROLLED = 62;
|
||||
private static final int LAST_PROFILE_FETCH = 63;
|
||||
private static final int SERVER_DELIVERED_TIMESTAMP = 64;
|
||||
|
||||
private static final int DATABASE_VERSION = 63;
|
||||
private static final int DATABASE_VERSION = 64;
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
@@ -916,6 +917,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL("ALTER TABLE recipient ADD COLUMN last_profile_fetch INTEGER DEFAULT 0");
|
||||
}
|
||||
|
||||
if (oldVersion < SERVER_DELIVERED_TIMESTAMP) {
|
||||
db.execSQL("ALTER TABLE push ADD COLUMN server_delivered_timestamp INTEGER DEFAULT 0");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
@@ -245,7 +245,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(), content.getServerTimestamp(), body, Optional.of(GroupId.v1orThrow(group.getGroupId())), 0, content.isNeedsReceipt());
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(Recipient.externalPush(context, content.getSender()).getId(), content.getSenderDevice(), content.getTimestamp(), content.getServerReceivedTimestamp(), body, Optional.of(GroupId.v1orThrow(group.getGroupId())), 0, content.isNeedsReceipt());
|
||||
IncomingGroupUpdateMessage groupMessage = new IncomingGroupUpdateMessage(incoming, storage, body);
|
||||
|
||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
||||
|
@@ -501,13 +501,14 @@ public final class PushProcessMessageJob extends BaseJob {
|
||||
RemotePeer remotePeer = new RemotePeer(Recipient.externalPush(context, content.getSender()).getId());
|
||||
|
||||
intent.setAction(WebRtcCallService.ACTION_RECEIVE_OFFER)
|
||||
.putExtra(WebRtcCallService.EXTRA_CALL_ID, message.getId())
|
||||
.putExtra(WebRtcCallService.EXTRA_REMOTE_PEER, remotePeer)
|
||||
.putExtra(WebRtcCallService.EXTRA_REMOTE_DEVICE, content.getSenderDevice())
|
||||
.putExtra(WebRtcCallService.EXTRA_OFFER_DESCRIPTION, message.getDescription())
|
||||
.putExtra(WebRtcCallService.EXTRA_TIMESTAMP, content.getTimestamp())
|
||||
.putExtra(WebRtcCallService.EXTRA_OFFER_TYPE, message.getType().getCode())
|
||||
.putExtra(WebRtcCallService.EXTRA_MULTI_RING, content.getCallMessage().get().isMultiRing());
|
||||
.putExtra(WebRtcCallService.EXTRA_CALL_ID, message.getId())
|
||||
.putExtra(WebRtcCallService.EXTRA_REMOTE_PEER, remotePeer)
|
||||
.putExtra(WebRtcCallService.EXTRA_REMOTE_DEVICE, content.getSenderDevice())
|
||||
.putExtra(WebRtcCallService.EXTRA_OFFER_DESCRIPTION, message.getDescription())
|
||||
.putExtra(WebRtcCallService.EXTRA_SERVER_RECEIVED_TIMESTAMP, content.getServerReceivedTimestamp())
|
||||
.putExtra(WebRtcCallService.EXTRA_SERVER_DELIVERED_TIMESTAMP, content.getServerDeliveredTimestamp())
|
||||
.putExtra(WebRtcCallService.EXTRA_OFFER_TYPE, message.getType().getCode())
|
||||
.putExtra(WebRtcCallService.EXTRA_MULTI_RING, content.getCallMessage().get().isMultiRing());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) context.startForegroundService(intent);
|
||||
else context.startService(intent);
|
||||
@@ -601,7 +602,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
||||
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Recipient.externalPush(context, content.getSender()).getId(),
|
||||
content.getSenderDevice(),
|
||||
content.getTimestamp(),
|
||||
content.getServerTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
"", Optional.absent(), 0,
|
||||
content.isNeedsReceipt());
|
||||
|
||||
@@ -710,7 +711,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
||||
Recipient sender = Recipient.externalPush(context, content.getSender());
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(sender.getId(),
|
||||
content.getTimestamp(),
|
||||
content.getServerTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
-1,
|
||||
expiresInSeconds * 1000L,
|
||||
true,
|
||||
@@ -768,7 +769,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
||||
Recipient sender = Recipient.externalPush(context, content.getSender());
|
||||
MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(delete.getTargetSentTimestamp(), sender.getId());
|
||||
|
||||
if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, sender, content.getServerTimestamp())) {
|
||||
if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, sender, content.getServerReceivedTimestamp())) {
|
||||
MessagingDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
|
||||
db.markAsRemoteDelete(targetMessage.getId());
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
|
||||
@@ -777,7 +778,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
||||
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), delete.getTargetSentTimestamp(), content);
|
||||
} else {
|
||||
Log.w(TAG, String.format(Locale.ENGLISH, "[handleRemoteDelete] Invalid remote delete! deleteTime: %d, targetTime: %d, deleteAuthor: %s, targetAuthor: %s",
|
||||
content.getServerTimestamp(), targetMessage.getServerTimestamp(), sender.getId(), targetMessage.getRecipient().getId()));
|
||||
content.getServerReceivedTimestamp(), targetMessage.getServerTimestamp(), sender.getId(), targetMessage.getRecipient().getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1025,7 +1026,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
||||
Optional<Attachment> sticker = getStickerAttachment(message.getSticker());
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(Recipient.externalPush(context, content.getSender()).getId(),
|
||||
message.getTimestamp(),
|
||||
content.getServerTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
-1,
|
||||
message.getExpiresInSeconds() * 1000L,
|
||||
false,
|
||||
@@ -1245,7 +1246,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
||||
IncomingTextMessage textMessage = new IncomingTextMessage(Recipient.externalPush(context, content.getSender()).getId(),
|
||||
content.getSenderDevice(),
|
||||
message.getTimestamp(),
|
||||
content.getServerTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
body,
|
||||
groupId,
|
||||
message.getExpiresInSeconds() * 1000L,
|
||||
|
@@ -95,26 +95,27 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
|
||||
private static final String TAG = WebRtcCallService.class.getSimpleName();
|
||||
|
||||
public static final String EXTRA_MUTE = "mute_value";
|
||||
public static final String EXTRA_AVAILABLE = "enabled_value";
|
||||
public static final String EXTRA_TIMESTAMP = "timestamp";
|
||||
public static final String EXTRA_CALL_ID = "call_id";
|
||||
public static final String EXTRA_RESULT_RECEIVER = "result_receiver";
|
||||
public static final String EXTRA_SPEAKER = "audio_speaker";
|
||||
public static final String EXTRA_BLUETOOTH = "audio_bluetooth";
|
||||
public static final String EXTRA_REMOTE_PEER = "remote_peer";
|
||||
public static final String EXTRA_REMOTE_DEVICE = "remote_device";
|
||||
public static final String EXTRA_OFFER_DESCRIPTION = "offer_description";
|
||||
public static final String EXTRA_OFFER_TYPE = "offer_type";
|
||||
public static final String EXTRA_MULTI_RING = "multi_ring";
|
||||
public static final String EXTRA_HANGUP_TYPE = "hangup_type";
|
||||
public static final String EXTRA_HANGUP_IS_LEGACY = "hangup_is_legacy";
|
||||
public static final String EXTRA_HANGUP_DEVICE_ID = "hangup_device_id";
|
||||
public static final String EXTRA_ANSWER_DESCRIPTION = "answer_description";
|
||||
public static final String EXTRA_ICE_CANDIDATES = "ice_candidates";
|
||||
public static final String EXTRA_ENABLE = "enable_value";
|
||||
public static final String EXTRA_BROADCAST = "broadcast";
|
||||
public static final String EXTRA_ANSWER_WITH_VIDEO = "enable_video";
|
||||
public static final String EXTRA_MUTE = "mute_value";
|
||||
public static final String EXTRA_AVAILABLE = "enabled_value";
|
||||
public static final String EXTRA_SERVER_RECEIVED_TIMESTAMP = "server_received_timestamp";
|
||||
public static final String EXTRA_SERVER_DELIVERED_TIMESTAMP = "server_delivered_timestamp";
|
||||
public static final String EXTRA_CALL_ID = "call_id";
|
||||
public static final String EXTRA_RESULT_RECEIVER = "result_receiver";
|
||||
public static final String EXTRA_SPEAKER = "audio_speaker";
|
||||
public static final String EXTRA_BLUETOOTH = "audio_bluetooth";
|
||||
public static final String EXTRA_REMOTE_PEER = "remote_peer";
|
||||
public static final String EXTRA_REMOTE_DEVICE = "remote_device";
|
||||
public static final String EXTRA_OFFER_DESCRIPTION = "offer_description";
|
||||
public static final String EXTRA_OFFER_TYPE = "offer_type";
|
||||
public static final String EXTRA_MULTI_RING = "multi_ring";
|
||||
public static final String EXTRA_HANGUP_TYPE = "hangup_type";
|
||||
public static final String EXTRA_HANGUP_IS_LEGACY = "hangup_is_legacy";
|
||||
public static final String EXTRA_HANGUP_DEVICE_ID = "hangup_device_id";
|
||||
public static final String EXTRA_ANSWER_DESCRIPTION = "answer_description";
|
||||
public static final String EXTRA_ICE_CANDIDATES = "ice_candidates";
|
||||
public static final String EXTRA_ENABLE = "enable_value";
|
||||
public static final String EXTRA_BROADCAST = "broadcast";
|
||||
public static final String EXTRA_ANSWER_WITH_VIDEO = "enable_video";
|
||||
|
||||
public static final String ACTION_OUTGOING_CALL = "CALL_OUTGOING";
|
||||
public static final String ACTION_DENY_CALL = "DENY_CALL";
|
||||
@@ -383,13 +384,14 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
// Handlers
|
||||
|
||||
private void handleReceivedOffer(Intent intent) {
|
||||
CallId callId = getCallId(intent);
|
||||
RemotePeer remotePeer = getRemotePeer(intent);
|
||||
Integer remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
|
||||
String offer = intent.getStringExtra(EXTRA_OFFER_DESCRIPTION);
|
||||
Long timeStamp = intent.getLongExtra(EXTRA_TIMESTAMP, -1);
|
||||
OfferMessage.Type offerType = OfferMessage.Type.fromCode(intent.getStringExtra(EXTRA_OFFER_TYPE));
|
||||
boolean isMultiRing = intent.getBooleanExtra(EXTRA_MULTI_RING, false);
|
||||
CallId callId = getCallId(intent);
|
||||
RemotePeer remotePeer = getRemotePeer(intent);
|
||||
Integer remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
|
||||
String offer = intent.getStringExtra(EXTRA_OFFER_DESCRIPTION);
|
||||
long serverReceivedTimestamp = intent.getLongExtra(EXTRA_SERVER_RECEIVED_TIMESTAMP, -1);
|
||||
long serverDeliveredTimestamp = intent.getLongExtra(EXTRA_SERVER_DELIVERED_TIMESTAMP, -1);
|
||||
OfferMessage.Type offerType = OfferMessage.Type.fromCode(intent.getStringExtra(EXTRA_OFFER_TYPE));
|
||||
boolean isMultiRing = intent.getBooleanExtra(EXTRA_MULTI_RING, false);
|
||||
|
||||
Log.i(TAG, "handleReceivedOffer(): id: " + callId.format(remoteDevice));
|
||||
|
||||
@@ -413,12 +415,8 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
|
||||
CallManager.CallMediaType callType = getCallMediaTypeFromOfferType(offerType);
|
||||
|
||||
long timeMilli = new Date().getTime();
|
||||
long messageAgeSec = 0L;
|
||||
if (timeMilli > timeStamp) {
|
||||
messageAgeSec = (timeMilli - timeStamp) / 1000;
|
||||
}
|
||||
Log.i(TAG, "handleReceivedOffer(): messageAgeSec: " + messageAgeSec);
|
||||
long messageAgeSec = Math.max(serverDeliveredTimestamp - serverReceivedTimestamp, 0) / 1000;
|
||||
Log.i(TAG, "handleReceivedOffer(): messageAgeSec: " + messageAgeSec + ", serverReceivedTimestamp: " + serverReceivedTimestamp + ", serverDeliveredTimestamp: " + serverDeliveredTimestamp);
|
||||
|
||||
try {
|
||||
callManager.receivedOffer(callId, remotePeer, remoteDevice, offer, messageAgeSec, callType, 1, isMultiRing, true);
|
||||
|
Reference in New Issue
Block a user