Search in sources :

Example 91 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class MultiDeviceContactUpdateJob method generateSingleContactUpdate.

private void generateSingleContactUpdate(@NonNull RecipientId recipientId) throws IOException, UntrustedIdentityException, NetworkException {
    WriteDetails writeDetails = createTempFile();
    try {
        DeviceContactsOutputStream out = new DeviceContactsOutputStream(writeDetails.outputStream);
        Recipient recipient = Recipient.resolved(recipientId);
        if (recipient.getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) {
            Log.w(TAG, recipientId + " not registered!");
            return;
        }
        Optional<IdentityRecord> identityRecord = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipient.getId());
        Optional<VerifiedMessage> verifiedMessage = getVerifiedMessage(recipient, identityRecord);
        Map<RecipientId, Integer> inboxPositions = SignalDatabase.threads().getInboxPositions();
        Set<RecipientId> archived = SignalDatabase.threads().getArchivedRecipients();
        out.write(new DeviceContact(RecipientUtil.toSignalServiceAddress(context, recipient), Optional.fromNullable(recipient.isGroup() || recipient.isSystemContact() ? recipient.getDisplayName(context) : null), getAvatar(recipient.getId(), recipient.getContactUri()), Optional.of(ChatColorsMapper.getMaterialColor(recipient.getChatColors()).serialize()), verifiedMessage, ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey()), recipient.isBlocked(), recipient.getExpiresInSeconds() > 0 ? Optional.of(recipient.getExpiresInSeconds()) : Optional.absent(), Optional.fromNullable(inboxPositions.get(recipientId)), archived.contains(recipientId)));
        out.close();
        long length = BlobProvider.getInstance().calculateFileSize(context, writeDetails.uri);
        sendUpdate(ApplicationDependencies.getSignalServiceMessageSender(), BlobProvider.getInstance().getStream(context, writeDetails.uri), length, false);
    } catch (InvalidNumberException e) {
        Log.w(TAG, e);
    } finally {
        BlobProvider.getInstance().delete(context, writeDetails.uri);
    }
}
Also used : DeviceContact(org.whispersystems.signalservice.api.messages.multidevice.DeviceContact) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) DeviceContactsOutputStream(org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsOutputStream) InvalidNumberException(org.whispersystems.signalservice.api.util.InvalidNumberException) IdentityRecord(org.thoughtcrime.securesms.database.model.IdentityRecord) Recipient(org.thoughtcrime.securesms.recipients.Recipient) VerifiedMessage(org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage)

Example 92 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupCallUpdateSendJob method create.

@WorkerThread
@NonNull
public static GroupCallUpdateSendJob create(@NonNull RecipientId recipientId, @Nullable String eraId) {
    Recipient conversationRecipient = Recipient.resolved(recipientId);
    if (!conversationRecipient.isPushV2Group()) {
        throw new AssertionError("We have a recipient, but it's not a V2 Group");
    }
    List<RecipientId> recipients = Stream.of(RecipientUtil.getEligibleForSending(conversationRecipient.getParticipants())).filterNot(Recipient::isSelf).filterNot(Recipient::isBlocked).map(Recipient::getId).toList();
    return new GroupCallUpdateSendJob(recipientId, eraId, recipients, recipients.size(), new Parameters.Builder().setQueue(conversationRecipient.getId().toQueueKey()).setLifespan(TimeUnit.MINUTES.toMillis(5)).setMaxAttempts(3).build());
}
Also used : RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) Recipient(org.thoughtcrime.securesms.recipients.Recipient) WorkerThread(androidx.annotation.WorkerThread) NonNull(androidx.annotation.NonNull)

Example 93 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupV1MigrationJob method enqueueRoutineMigrationsIfNecessary.

public static void enqueueRoutineMigrationsIfNecessary(@NonNull Application application) {
    if (!SignalStore.registrationValues().isRegistrationComplete() || !SignalStore.account().isRegistered() || SignalStore.account().getAci() == null) {
        Log.i(TAG, "Registration not complete. Skipping.");
        return;
    }
    long timeSinceRefresh = System.currentTimeMillis() - SignalStore.misc().getLastGv1RoutineMigrationTime();
    if (timeSinceRefresh < REFRESH_INTERVAL) {
        Log.i(TAG, "Too soon to refresh. Did the last refresh " + timeSinceRefresh + " ms ago.");
        return;
    }
    SignalStore.misc().setLastGv1RoutineMigrationTime(System.currentTimeMillis());
    SignalExecutors.BOUNDED.execute(() -> {
        JobManager jobManager = ApplicationDependencies.getJobManager();
        List<ThreadRecord> threads = SignalDatabase.threads().getRecentV1Groups(ROUTINE_LIMIT);
        Set<RecipientId> needsRefresh = new HashSet<>();
        if (threads.size() > 0) {
            Log.d(TAG, "About to enqueue refreshes for " + threads.size() + " groups.");
        }
        for (ThreadRecord thread : threads) {
            jobManager.add(new GroupV1MigrationJob(thread.getRecipient().getId()));
            needsRefresh.addAll(Stream.of(thread.getRecipient().getParticipants()).filter(r -> r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED || r.getGroupsV1MigrationCapability() != Recipient.Capability.SUPPORTED).map(Recipient::getId).toList());
        }
        if (needsRefresh.size() > 0) {
            Log.w(TAG, "Enqueuing profile refreshes for " + needsRefresh.size() + " GV1 participants.");
            RetrieveProfileJob.enqueue(needsRefresh);
        }
    });
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) GroupsV1MigrationUtil(org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil) SignalDatabase(org.thoughtcrime.securesms.database.SignalDatabase) RetryLaterException(org.thoughtcrime.securesms.transport.RetryLaterException) Stream(com.annimon.stream.Stream) NonNull(androidx.annotation.NonNull) Data(org.thoughtcrime.securesms.jobmanager.Data) JobManager(org.thoughtcrime.securesms.jobmanager.JobManager) HashSet(java.util.HashSet) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) NoCredentialForRedemptionTimeException(org.whispersystems.signalservice.api.groupsv2.NoCredentialForRedemptionTimeException) Recipient(org.thoughtcrime.securesms.recipients.Recipient) GroupChangeBusyException(org.thoughtcrime.securesms.groups.GroupChangeBusyException) ThreadRecord(org.thoughtcrime.securesms.database.model.ThreadRecord) SignalExecutors(org.signal.core.util.concurrent.SignalExecutors) PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Set(java.util.Set) NetworkConstraint(org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint) IOException(java.io.IOException) TimeUnit(java.util.concurrent.TimeUnit) Log(org.signal.core.util.logging.Log) List(java.util.List) Application(android.app.Application) Job(org.thoughtcrime.securesms.jobmanager.Job) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) ThreadRecord(org.thoughtcrime.securesms.database.model.ThreadRecord) Recipient(org.thoughtcrime.securesms.recipients.Recipient) JobManager(org.thoughtcrime.securesms.jobmanager.JobManager) HashSet(java.util.HashSet)

Example 94 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class PaymentSendJob method onRun.

@Override
protected void onRun() throws Exception {
    if (!Recipient.self().isRegistered()) {
        throw new NotPushRegisteredException();
    }
    if (!SignalStore.paymentsValues().mobileCoinPaymentsEnabled()) {
        Log.w(TAG, "Payments are not enabled");
        return;
    }
    Stopwatch stopwatch = new Stopwatch("Payment submission");
    Wallet wallet = ApplicationDependencies.getPayments().getWallet();
    PaymentDatabase paymentDatabase = SignalDatabase.payments();
    paymentDatabase.createOutgoingPayment(uuid, recipientId, publicAddress, timestamp, note, amount);
    Log.i(TAG, "Payment record created " + uuid);
    stopwatch.split("Record created");
    try {
        PaymentSubmissionResult paymentSubmissionResult = wallet.sendPayment(publicAddress, amount.requireMobileCoin(), totalFee.requireMobileCoin());
        stopwatch.split("Payment submitted");
        if (paymentSubmissionResult.containsDefrags()) {
            Log.i(TAG, "Payment contains " + paymentSubmissionResult.defrags().size() + " defrags, main payment" + uuid);
            RecipientId self = Recipient.self().getId();
            MobileCoinPublicAddress selfAddress = wallet.getMobileCoinPublicAddress();
            for (TransactionSubmissionResult defrag : paymentSubmissionResult.defrags()) {
                UUID defragUuid = UUID.randomUUID();
                PaymentTransactionId.MobileCoin mobileCoinTransaction = (PaymentTransactionId.MobileCoin) defrag.getTransactionId();
                paymentDatabase.createDefrag(defragUuid, self, selfAddress, timestamp - 1, mobileCoinTransaction.getFee(), mobileCoinTransaction.getTransaction(), mobileCoinTransaction.getReceipt());
                Log.i(TAG, "Defrag entered with id " + defragUuid);
                ApplicationDependencies.getJobManager().startChain(new PaymentTransactionCheckJob(defragUuid, QUEUE)).then(new MultiDeviceOutgoingPaymentSyncJob(defragUuid)).enqueue();
            }
            stopwatch.split("Defrag");
        }
        TransactionSubmissionResult.ErrorCode errorCode = paymentSubmissionResult.getErrorCode();
        switch(errorCode) {
            case INSUFFICIENT_FUNDS:
                paymentDatabase.markPaymentFailed(uuid, FailureReason.INSUFFICIENT_FUNDS);
                throw new PaymentException("Payment failed due to " + errorCode);
            case GENERIC_FAILURE:
                paymentDatabase.markPaymentFailed(uuid, FailureReason.UNKNOWN);
                throw new PaymentException("Payment failed due to " + errorCode);
            case NETWORK_FAILURE:
                paymentDatabase.markPaymentFailed(uuid, FailureReason.NETWORK);
                throw new PaymentException("Payment failed due to " + errorCode);
            case NONE:
                Log.i(TAG, "Payment submission complete");
                TransactionSubmissionResult transactionSubmissionResult = Objects.requireNonNull(paymentSubmissionResult.getNonDefrag());
                PaymentTransactionId.MobileCoin mobileCoinTransaction = (PaymentTransactionId.MobileCoin) transactionSubmissionResult.getTransactionId();
                paymentDatabase.markPaymentSubmitted(uuid, mobileCoinTransaction.getTransaction(), mobileCoinTransaction.getReceipt(), mobileCoinTransaction.getFee());
                Log.i(TAG, "Payment record updated " + uuid);
                break;
        }
    } catch (Exception e) {
        Log.w(TAG, "Unknown payment failure", e);
        paymentDatabase.markPaymentFailed(uuid, FailureReason.UNKNOWN);
        throw e;
    }
    stopwatch.split("Update database record");
    stopwatch.stop(TAG);
}
Also used : PaymentTransactionId(org.thoughtcrime.securesms.payments.PaymentTransactionId) PaymentSubmissionResult(org.thoughtcrime.securesms.payments.PaymentSubmissionResult) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) Wallet(org.thoughtcrime.securesms.payments.Wallet) NotPushRegisteredException(org.thoughtcrime.securesms.net.NotPushRegisteredException) Stopwatch(org.thoughtcrime.securesms.util.Stopwatch) NotPushRegisteredException(org.thoughtcrime.securesms.net.NotPushRegisteredException) TransactionSubmissionResult(org.thoughtcrime.securesms.payments.TransactionSubmissionResult) PaymentDatabase(org.thoughtcrime.securesms.database.PaymentDatabase) UUID(java.util.UUID) MobileCoinPublicAddress(org.thoughtcrime.securesms.payments.MobileCoinPublicAddress)

Example 95 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class MultiDeviceGroupUpdateJob method onRun.

@Override
public void onRun() throws Exception {
    if (!Recipient.self().isRegistered()) {
        throw new NotPushRegisteredException();
    }
    if (!TextSecurePreferences.isMultiDevice(context)) {
        Log.i(TAG, "Not multi device, aborting...");
        return;
    }
    if (SignalStore.account().isLinkedDevice()) {
        Log.i(TAG, "Not primary device, aborting...");
        return;
    }
    ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
    InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pipe[0]);
    Uri uri = BlobProvider.getInstance().forData(inputStream, 0).withFileName("multidevice-group-update").createForSingleSessionOnDiskAsync(context, () -> Log.i(TAG, "Write successful."), e -> Log.w(TAG, "Error during write.", e));
    try (GroupDatabase.Reader reader = SignalDatabase.groups().getGroups()) {
        DeviceGroupsOutputStream out = new DeviceGroupsOutputStream(new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]));
        boolean hasData = false;
        GroupDatabase.GroupRecord record;
        while ((record = reader.getNext()) != null) {
            if (record.isV1Group()) {
                List<SignalServiceAddress> members = new LinkedList<>();
                List<Recipient> registeredMembers = RecipientUtil.getEligibleForSending(Recipient.resolvedList(record.getMembers()));
                for (Recipient member : registeredMembers) {
                    members.add(RecipientUtil.toSignalServiceAddress(context, member));
                }
                RecipientId recipientId = SignalDatabase.recipients().getOrInsertFromPossiblyMigratedGroupId(record.getId());
                Recipient recipient = Recipient.resolved(recipientId);
                Optional<Integer> expirationTimer = recipient.getExpiresInSeconds() > 0 ? Optional.of(recipient.getExpiresInSeconds()) : Optional.absent();
                Map<RecipientId, Integer> inboxPositions = SignalDatabase.threads().getInboxPositions();
                Set<RecipientId> archived = SignalDatabase.threads().getArchivedRecipients();
                out.write(new DeviceGroup(record.getId().getDecodedId(), Optional.fromNullable(record.getTitle()), members, getAvatar(record.getRecipientId()), record.isActive(), expirationTimer, Optional.of(ChatColorsMapper.getMaterialColor(recipient.getChatColors()).serialize()), recipient.isBlocked(), Optional.fromNullable(inboxPositions.get(recipientId)), archived.contains(recipientId)));
                hasData = true;
            }
        }
        out.close();
        if (hasData) {
            long length = BlobProvider.getInstance().calculateFileSize(context, uri);
            sendUpdate(ApplicationDependencies.getSignalServiceMessageSender(), BlobProvider.getInstance().getStream(context, uri), length);
        } else {
            Log.w(TAG, "No groups present for sync message. Sending an empty update.");
            sendUpdate(ApplicationDependencies.getSignalServiceMessageSender(), null, 0);
        }
    } finally {
        BlobProvider.getInstance().delete(context, uri);
    }
}
Also used : RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) InputStream(java.io.InputStream) NotPushRegisteredException(org.thoughtcrime.securesms.net.NotPushRegisteredException) DeviceGroup(org.whispersystems.signalservice.api.messages.multidevice.DeviceGroup) Recipient(org.thoughtcrime.securesms.recipients.Recipient) Uri(android.net.Uri) LinkedList(java.util.LinkedList) ParcelFileDescriptor(android.os.ParcelFileDescriptor) GroupDatabase(org.thoughtcrime.securesms.database.GroupDatabase) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) DeviceGroupsOutputStream(org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsOutputStream)

Aggregations

RecipientId (org.thoughtcrime.securesms.recipients.RecipientId)154 NonNull (androidx.annotation.NonNull)70 Recipient (org.thoughtcrime.securesms.recipients.Recipient)70 List (java.util.List)34 ArrayList (java.util.ArrayList)33 Nullable (androidx.annotation.Nullable)32 Context (android.content.Context)31 Log (org.signal.core.util.logging.Log)31 IOException (java.io.IOException)30 ApplicationDependencies (org.thoughtcrime.securesms.dependencies.ApplicationDependencies)29 WorkerThread (androidx.annotation.WorkerThread)28 Stream (com.annimon.stream.Stream)27 LinkedList (java.util.LinkedList)25 ContentValues (android.content.ContentValues)24 Cursor (android.database.Cursor)24 Collections (java.util.Collections)24 SignalDatabase (org.thoughtcrime.securesms.database.SignalDatabase)24 GroupDatabase (org.thoughtcrime.securesms.database.GroupDatabase)23 Optional (org.whispersystems.libsignal.util.guava.Optional)22 HashSet (java.util.HashSet)21