mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-24 03:35:58 +00:00
Fix group call flickering missed.
This commit is contained in:
committed by
Greyson Parrelli
parent
3c10966a36
commit
d424a60345
@@ -605,22 +605,6 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
||||
return handleCallLinkUpdate(callRecipient, timestamp, CallId.fromEra(eraId), Direction.INCOMING)
|
||||
}
|
||||
|
||||
fun insertOrUpdateGroupCallFromExternalEvent(
|
||||
groupRecipientId: RecipientId,
|
||||
sender: RecipientId,
|
||||
timestamp: Long,
|
||||
messageGroupCallEraId: String?
|
||||
) {
|
||||
insertOrUpdateGroupCallFromLocalEvent(
|
||||
groupRecipientId,
|
||||
sender,
|
||||
timestamp,
|
||||
messageGroupCallEraId,
|
||||
emptyList(),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
fun insertOrUpdateGroupCallFromLocalEvent(
|
||||
groupRecipientId: RecipientId,
|
||||
sender: RecipientId,
|
||||
|
||||
@@ -44,7 +44,7 @@ public class JobManager implements ConstraintObserver.Notifier {
|
||||
|
||||
private static final String TAG = Log.tag(JobManager.class);
|
||||
|
||||
public static final int CURRENT_VERSION = 11;
|
||||
public static final int CURRENT_VERSION = 12;
|
||||
|
||||
private final Application application;
|
||||
private final Configuration configuration;
|
||||
|
||||
@@ -50,6 +50,18 @@ public class JsonJobData {
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable JsonJobData deserializeOrNull(@Nullable byte[] data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return JsonUtils.fromJson(data, JsonJobData.class);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private JsonJobData(@JsonProperty("strings") @NonNull Map<String, String> strings,
|
||||
@JsonProperty("stringArrays") @NonNull Map<String, String[]> stringArrays,
|
||||
@JsonProperty("integers") @NonNull Map<String, Integer> integers,
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.jobmanager.migrations
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.JobMigration
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData
|
||||
import org.thoughtcrime.securesms.jobs.protos.GroupCallPeekJobData
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
/**
|
||||
* Migrate jobs with just the recipient id to utilize the new data proto.
|
||||
*/
|
||||
class GroupCallPeekJobDataMigration : JobMigration(12) {
|
||||
|
||||
companion object {
|
||||
private const val KEY_GROUP_RECIPIENT_ID: String = "group_recipient_id"
|
||||
private val GROUP_PEEK_JOB_KEYS = arrayOf("GroupCallPeekJob", "GroupCallPeekWorkerJob")
|
||||
}
|
||||
|
||||
override fun migrate(jobData: JobData): JobData {
|
||||
if (jobData.factoryKey !in GROUP_PEEK_JOB_KEYS) {
|
||||
return jobData
|
||||
}
|
||||
|
||||
val data = jobData.data ?: return jobData
|
||||
val jsonData = JsonJobData.deserializeOrNull(data) ?: return jobData
|
||||
val recipientId = jsonData.getStringOrDefault(KEY_GROUP_RECIPIENT_ID, null) ?: return jobData
|
||||
|
||||
val jobProto = GroupCallPeekJobData(
|
||||
groupRecipientId = recipientId.toLong(),
|
||||
senderRecipientId = RecipientId.UNKNOWN.toLong(),
|
||||
serverTimestamp = 0L
|
||||
)
|
||||
|
||||
return jobData.withData(jobProto.encode())
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,13 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.DecryptionsDrainedConstraint;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.jobs.protos.GroupCallPeekJobData;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Allows the enqueueing of one peek operation per group while the web socket is not drained.
|
||||
@@ -19,32 +21,30 @@ public final class GroupCallPeekJob extends BaseJob {
|
||||
|
||||
private static final String QUEUE = "__GroupCallPeekJob__";
|
||||
|
||||
private static final String KEY_GROUP_RECIPIENT_ID = "group_recipient_id";
|
||||
@NonNull private final GroupCallPeekJobData groupCallPeekJobData;
|
||||
|
||||
@NonNull private final RecipientId groupRecipientId;
|
||||
|
||||
public static void enqueue(@NonNull RecipientId groupRecipientId) {
|
||||
public static void enqueue(@NonNull GroupCallPeekJobData groupCallPeekJobData) {
|
||||
JobManager jobManager = AppDependencies.getJobManager();
|
||||
String queue = QUEUE + groupRecipientId.serialize();
|
||||
String queue = QUEUE + groupCallPeekJobData.groupRecipientId;
|
||||
Parameters.Builder parameters = new Parameters.Builder()
|
||||
.setQueue(queue)
|
||||
.addConstraint(DecryptionsDrainedConstraint.KEY);
|
||||
|
||||
jobManager.cancelAllInQueue(queue);
|
||||
|
||||
jobManager.add(new GroupCallPeekJob(parameters.build(), groupRecipientId));
|
||||
jobManager.add(new GroupCallPeekJob(parameters.build(), groupCallPeekJobData));
|
||||
}
|
||||
|
||||
private GroupCallPeekJob(@NonNull Parameters parameters,
|
||||
@NonNull RecipientId groupRecipientId)
|
||||
@NonNull GroupCallPeekJobData groupCallPeekJobData)
|
||||
{
|
||||
super(parameters);
|
||||
this.groupRecipientId = groupRecipientId;
|
||||
this.groupCallPeekJobData = groupCallPeekJobData;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRun() {
|
||||
AppDependencies.getJobManager().add(new GroupCallPeekWorkerJob(groupRecipientId));
|
||||
AppDependencies.getJobManager().add(new GroupCallPeekWorkerJob(groupCallPeekJobData));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,10 +53,8 @@ public final class GroupCallPeekJob extends BaseJob {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable byte[] serialize() {
|
||||
return new JsonJobData.Builder()
|
||||
.putString(KEY_GROUP_RECIPIENT_ID, groupRecipientId.serialize())
|
||||
.serialize();
|
||||
public @NonNull byte[] serialize() {
|
||||
return groupCallPeekJobData.encode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,8 +70,12 @@ public final class GroupCallPeekJob extends BaseJob {
|
||||
|
||||
@Override
|
||||
public @NonNull GroupCallPeekJob create(@NonNull Parameters parameters, @Nullable byte[] serializedData) {
|
||||
JsonJobData data = JsonJobData.deserialize(serializedData);
|
||||
return new GroupCallPeekJob(parameters, RecipientId.from(data.getString(KEY_GROUP_RECIPIENT_ID)));
|
||||
try {
|
||||
GroupCallPeekJobData jobData = GroupCallPeekJobData.ADAPTER.decode(serializedData);
|
||||
return new GroupCallPeekJob(parameters, jobData);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,15 @@ package org.thoughtcrime.securesms.jobs;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobs.protos.GroupCallPeekJobData;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.service.webrtc.WebRtcUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Runs in the same queue as messages for the group.
|
||||
@@ -15,26 +20,42 @@ final class GroupCallPeekWorkerJob extends BaseJob {
|
||||
|
||||
public static final String KEY = "GroupCallPeekWorkerJob";
|
||||
|
||||
private static final String KEY_GROUP_RECIPIENT_ID = "group_recipient_id";
|
||||
private static final String KEY_GROUP_CALL_JOB_DATA = "group_call_job_data";
|
||||
|
||||
@NonNull private final RecipientId groupRecipientId;
|
||||
@NonNull private final GroupCallPeekJobData groupCallPeekJobData;
|
||||
|
||||
public GroupCallPeekWorkerJob(@NonNull RecipientId groupRecipientId) {
|
||||
public GroupCallPeekWorkerJob(@NonNull GroupCallPeekJobData groupCallPeekJobData) {
|
||||
this(new Parameters.Builder()
|
||||
.setQueue(PushProcessMessageJob.getQueueName(groupRecipientId))
|
||||
.setQueue(PushProcessMessageJob.getQueueName(RecipientId.from(groupCallPeekJobData.groupRecipientId)))
|
||||
.setMaxInstancesForQueue(2)
|
||||
.build(),
|
||||
groupRecipientId);
|
||||
groupCallPeekJobData);
|
||||
}
|
||||
|
||||
private GroupCallPeekWorkerJob(@NonNull Parameters parameters, @NonNull RecipientId groupRecipientId) {
|
||||
private GroupCallPeekWorkerJob(@NonNull Parameters parameters, @NonNull GroupCallPeekJobData groupCallPeekJobData) {
|
||||
super(parameters);
|
||||
this.groupRecipientId = groupRecipientId;
|
||||
this.groupCallPeekJobData = groupCallPeekJobData;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRun() {
|
||||
AppDependencies.getSignalCallManager().peekGroupCall(groupRecipientId);
|
||||
RecipientId groupRecipientId = RecipientId.from(groupCallPeekJobData.groupRecipientId);
|
||||
|
||||
AppDependencies.getSignalCallManager().peekGroupCall(groupRecipientId, (peekInfo) -> {
|
||||
if (groupCallPeekJobData.senderRecipientId == RecipientId.UNKNOWN.toLong()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RecipientId senderRecipientId = RecipientId.from(groupCallPeekJobData.senderRecipientId);
|
||||
SignalDatabase.calls().insertOrUpdateGroupCallFromLocalEvent(
|
||||
groupRecipientId,
|
||||
senderRecipientId,
|
||||
groupCallPeekJobData.serverTimestamp,
|
||||
peekInfo.getEraId(),
|
||||
peekInfo.getJoinedMembers(),
|
||||
WebRtcUtil.isCallFull(peekInfo)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,10 +64,8 @@ final class GroupCallPeekWorkerJob extends BaseJob {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable byte[] serialize() {
|
||||
return new JsonJobData.Builder()
|
||||
.putString(KEY_GROUP_RECIPIENT_ID, groupRecipientId.serialize())
|
||||
.serialize();
|
||||
public @NonNull byte[] serialize() {
|
||||
return groupCallPeekJobData.encode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,8 +81,12 @@ final class GroupCallPeekWorkerJob extends BaseJob {
|
||||
|
||||
@Override
|
||||
public @NonNull GroupCallPeekWorkerJob create(@NonNull Parameters parameters, @Nullable byte[] serializedData) {
|
||||
JsonJobData data = JsonJobData.deserialize(serializedData);
|
||||
return new GroupCallPeekWorkerJob(parameters, RecipientId.from(data.getString(KEY_GROUP_RECIPIENT_ID)));
|
||||
try {
|
||||
GroupCallPeekJobData jobData = GroupCallPeekJobData.ADAPTER.decode(serializedData);
|
||||
return new GroupCallPeekWorkerJob(parameters, jobData);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.WifiConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.migrations.DonationReceiptRedemptionJobMigration;
|
||||
import org.thoughtcrime.securesms.jobmanager.migrations.GroupCallPeekJobDataMigration;
|
||||
import org.thoughtcrime.securesms.jobmanager.migrations.PushDecryptMessageJobEnvelopeMigration;
|
||||
import org.thoughtcrime.securesms.jobmanager.migrations.PushProcessMessageJobMigration;
|
||||
import org.thoughtcrime.securesms.jobmanager.migrations.PushProcessMessageQueueJobMigration;
|
||||
@@ -380,6 +381,7 @@ public final class JobManagerFactories {
|
||||
new PushDecryptMessageJobEnvelopeMigration(),
|
||||
new SenderKeyDistributionSendJobRecipientMigration(),
|
||||
new PushProcessMessageJobMigration(),
|
||||
new DonationReceiptRedemptionJobMigration());
|
||||
new DonationReceiptRedemptionJobMigration(),
|
||||
new GroupCallPeekJobDataMigration());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ import org.thoughtcrime.securesms.jobs.RefreshAttributesJob
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob
|
||||
import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob
|
||||
import org.thoughtcrime.securesms.jobs.TrimThreadJob
|
||||
import org.thoughtcrime.securesms.jobs.protos.GroupCallPeekJobData
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil
|
||||
@@ -1016,14 +1017,13 @@ object DataMessageProcessor {
|
||||
|
||||
val groupRecipientId = SignalDatabase.recipients.getOrInsertFromPossiblyMigratedGroupId(groupId)
|
||||
|
||||
SignalDatabase.calls.insertOrUpdateGroupCallFromExternalEvent(
|
||||
groupRecipientId,
|
||||
senderRecipientId,
|
||||
envelope.serverTimestamp!!,
|
||||
groupCallUpdate.eraId
|
||||
GroupCallPeekJob.enqueue(
|
||||
GroupCallPeekJobData(
|
||||
groupRecipientId.toLong(),
|
||||
senderRecipientId.toLong(),
|
||||
envelope.serverTimestamp!!
|
||||
)
|
||||
)
|
||||
|
||||
GroupCallPeekJob.enqueue(groupRecipientId)
|
||||
}
|
||||
|
||||
fun notifyTypingStoppedFromIncomingMessage(context: Context, senderRecipient: Recipient, threadRecipientId: RecipientId, device: Int) {
|
||||
|
||||
@@ -103,6 +103,7 @@ import java.util.UUID;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.reactivex.rxjava3.core.Flowable;
|
||||
@@ -446,6 +447,10 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
}
|
||||
|
||||
public void peekGroupCall(@NonNull RecipientId id) {
|
||||
peekGroupCall(id, null);
|
||||
}
|
||||
|
||||
public void peekGroupCall(@NonNull RecipientId id, @Nullable Consumer<PeekInfo> onWillUpdateCallFromPeek) {
|
||||
if (callManager == null) {
|
||||
Log.i(TAG, "Unable to peekGroupCall, call manager is null");
|
||||
return;
|
||||
@@ -464,6 +469,10 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||
Long threadId = SignalDatabase.threads().getThreadIdFor(group.getId());
|
||||
|
||||
if (threadId != null) {
|
||||
if (onWillUpdateCallFromPeek != null) {
|
||||
onWillUpdateCallFromPeek.accept(peekInfo);
|
||||
}
|
||||
|
||||
SignalDatabase.calls()
|
||||
.updateGroupCallFromPeek(threadId,
|
||||
peekInfo.getEraId(),
|
||||
|
||||
Reference in New Issue
Block a user