Search in sources :

Example 1 with ProfileAndCredential

use of org.whispersystems.signalservice.api.profiles.ProfileAndCredential in project Signal-Android by WhisperSystems.

the class ProfileService method getProfile.

public Single<ServiceResponse<ProfileAndCredential>> getProfile(SignalServiceAddress address, Optional<ProfileKey> profileKey, Optional<UnidentifiedAccess> unidentifiedAccess, SignalServiceProfile.RequestType requestType, Locale locale) {
    ServiceId serviceId = address.getServiceId();
    SecureRandom random = new SecureRandom();
    ProfileKeyCredentialRequestContext requestContext = null;
    WebSocketProtos.WebSocketRequestMessage.Builder builder = WebSocketProtos.WebSocketRequestMessage.newBuilder().setId(random.nextLong()).setVerb("GET");
    if (profileKey.isPresent()) {
        ProfileKeyVersion profileKeyIdentifier = profileKey.get().getProfileKeyVersion(serviceId.uuid());
        String version = profileKeyIdentifier.serialize();
        if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL) {
            requestContext = clientZkProfileOperations.createProfileKeyCredentialRequestContext(random, serviceId.uuid(), profileKey.get());
            ProfileKeyCredentialRequest request = requestContext.getRequest();
            String credentialRequest = Hex.toStringCondensed(request.serialize());
            builder.setPath(String.format("/v1/profile/%s/%s/%s", serviceId, version, credentialRequest));
        } else {
            builder.setPath(String.format("/v1/profile/%s/%s", serviceId, version));
        }
    } else {
        builder.setPath(String.format("/v1/profile/%s", address.getIdentifier()));
    }
    builder.addHeaders(AcceptLanguagesUtil.getAcceptLanguageHeader(locale));
    WebSocketProtos.WebSocketRequestMessage requestMessage = builder.build();
    ResponseMapper<ProfileAndCredential> responseMapper = DefaultResponseMapper.extend(ProfileAndCredential.class).withResponseMapper(new ProfileResponseMapper(requestType, requestContext)).build();
    return signalWebSocket.request(requestMessage, unidentifiedAccess).map(responseMapper::map).onErrorResumeNext(t -> restFallback(address, profileKey, unidentifiedAccess, requestType, locale)).onErrorReturn(ServiceResponse::forUnknownError);
}
Also used : Single(io.reactivex.rxjava3.core.Single) AcceptLanguagesUtil(org.whispersystems.signalservice.internal.push.http.AcceptLanguagesUtil) MalformedResponseException(org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException) SignalServiceMessageReceiver(org.whispersystems.signalservice.api.SignalServiceMessageReceiver) VerificationFailedException(org.signal.zkgroup.VerificationFailedException) SignalWebSocket(org.whispersystems.signalservice.api.SignalWebSocket) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) SignalServiceProfile(org.whispersystems.signalservice.api.profiles.SignalServiceProfile) SecureRandom(java.security.SecureRandom) UnidentifiedAccess(org.whispersystems.signalservice.api.crypto.UnidentifiedAccess) Pair(org.whispersystems.libsignal.util.Pair) ProfileAndCredential(org.whispersystems.signalservice.api.profiles.ProfileAndCredential) ProfileKeyCredentialRequest(org.signal.zkgroup.profiles.ProfileKeyCredentialRequest) Locale(java.util.Locale) Hex(org.whispersystems.signalservice.internal.util.Hex) DefaultResponseMapper(org.whispersystems.signalservice.internal.websocket.DefaultResponseMapper) ClientZkProfileOperations(org.signal.zkgroup.profiles.ClientZkProfileOperations) ProfileKeyCredential(org.signal.zkgroup.profiles.ProfileKeyCredential) ACI(org.whispersystems.signalservice.api.push.ACI) WebSocketProtos(org.whispersystems.signalservice.internal.websocket.WebSocketProtos) ProfileKeyVersion(org.signal.zkgroup.profiles.ProfileKeyVersion) Function(org.whispersystems.libsignal.util.guava.Function) ServiceResponse(org.whispersystems.signalservice.internal.ServiceResponse) JsonUtil(org.whispersystems.signalservice.internal.util.JsonUtil) Optional(org.whispersystems.libsignal.util.guava.Optional) TimeUnit(java.util.concurrent.TimeUnit) ProfileKeyCredentialRequestContext(org.signal.zkgroup.profiles.ProfileKeyCredentialRequestContext) ResponseMapper(org.whispersystems.signalservice.internal.websocket.ResponseMapper) ServiceResponseProcessor(org.whispersystems.signalservice.internal.ServiceResponseProcessor) ServiceId(org.whispersystems.signalservice.api.push.ServiceId) SecureRandom(java.security.SecureRandom) ProfileAndCredential(org.whispersystems.signalservice.api.profiles.ProfileAndCredential) ProfileKeyCredentialRequestContext(org.signal.zkgroup.profiles.ProfileKeyCredentialRequestContext) ServiceId(org.whispersystems.signalservice.api.push.ServiceId) ServiceResponse(org.whispersystems.signalservice.internal.ServiceResponse) ProfileKeyCredentialRequest(org.signal.zkgroup.profiles.ProfileKeyCredentialRequest) ProfileKeyVersion(org.signal.zkgroup.profiles.ProfileKeyVersion) WebSocketProtos(org.whispersystems.signalservice.internal.websocket.WebSocketProtos)

Example 2 with ProfileAndCredential

use of org.whispersystems.signalservice.api.profiles.ProfileAndCredential in project Signal-Android by WhisperSystems.

the class RetrieveProfileJob method onRun.

@Override
public void onRun() throws IOException, RetryLaterException {
    if (!SignalStore.account().isRegistered()) {
        Log.w(TAG, "Unregistered. Skipping.");
        return;
    }
    Stopwatch stopwatch = new Stopwatch("RetrieveProfile");
    RecipientDatabase recipientDatabase = SignalDatabase.recipients();
    RecipientUtil.ensureUuidsAreAvailable(context, Stream.of(Recipient.resolvedList(recipientIds)).filter(r -> r.getRegistered() != RecipientDatabase.RegisteredState.NOT_REGISTERED).toList());
    List<Recipient> recipients = Recipient.resolvedList(recipientIds);
    stopwatch.split("resolve-ensure");
    ProfileService profileService = new ProfileService(ApplicationDependencies.getGroupsV2Operations().getProfileOperations(), ApplicationDependencies.getSignalServiceMessageReceiver(), ApplicationDependencies.getSignalWebSocket());
    List<Observable<Pair<Recipient, ServiceResponse<ProfileAndCredential>>>> requests = Stream.of(recipients).filter(Recipient::hasServiceId).map(r -> ProfileUtil.retrieveProfile(context, r, getRequestType(r), profileService).toObservable()).toList();
    stopwatch.split("requests");
    OperationState operationState = Observable.mergeDelayError(requests).observeOn(Schedulers.io(), true).scan(new OperationState(), (state, pair) -> {
        Recipient recipient = pair.first();
        ProfileService.ProfileResponseProcessor processor = new ProfileService.ProfileResponseProcessor(pair.second());
        if (processor.hasResult()) {
            state.profiles.add(processor.getResult(recipient));
        } else if (processor.notFound()) {
            Log.w(TAG, "Failed to find a profile for " + recipient.getId());
            if (recipient.isRegistered()) {
                state.unregistered.add(recipient.getId());
            }
        } else if (processor.genericIoError()) {
            state.retries.add(recipient.getId());
        } else {
            Log.w(TAG, "Failed to retrieve profile for " + recipient.getId());
        }
        return state;
    }).lastOrError().blockingGet();
    stopwatch.split("responses");
    Set<RecipientId> success = SetUtil.difference(recipientIds, operationState.retries);
    Map<RecipientId, ServiceId> newlyRegistered = Stream.of(operationState.profiles).map(Pair::first).filterNot(Recipient::isRegistered).collect(Collectors.toMap(Recipient::getId, r -> r.getServiceId().orNull()));
    // noinspection SimplifyStreamApiCallChains
    Util.chunk(operationState.profiles, 150).stream().forEach(list -> {
        SignalDatabase.runInTransaction(() -> {
            for (Pair<Recipient, ProfileAndCredential> profile : list) {
                process(profile.first(), profile.second());
            }
        });
    });
    recipientDatabase.markProfilesFetched(success, System.currentTimeMillis());
    if (operationState.unregistered.size() > 0 || newlyRegistered.size() > 0) {
        Log.i(TAG, "Marking " + newlyRegistered.size() + " users as registered and " + operationState.unregistered.size() + " users as unregistered.");
        recipientDatabase.bulkUpdatedRegisteredStatus(newlyRegistered, operationState.unregistered);
    }
    stopwatch.split("process");
    for (Pair<Recipient, ProfileAndCredential> profile : operationState.profiles) {
        setIdentityKey(profile.first(), profile.second().getProfile().getIdentityKey());
    }
    stopwatch.split("identityKeys");
    long keyCount = Stream.of(operationState.profiles).map(Pair::first).map(Recipient::getProfileKey).withoutNulls().count();
    Log.d(TAG, String.format(Locale.US, "Started with %d recipient(s). Found %d profile(s), and had keys for %d of them. Will retry %d.", recipients.size(), operationState.profiles.size(), keyCount, operationState.retries.size()));
    stopwatch.stop(TAG);
    recipientIds.clear();
    recipientIds.addAll(operationState.retries);
    if (recipientIds.size() > 0) {
        throw new RetryLaterException();
    }
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) NonNull(androidx.annotation.NonNull) Data(org.thoughtcrime.securesms.jobmanager.Data) JobManager(org.thoughtcrime.securesms.jobmanager.JobManager) RecipientUtil(org.thoughtcrime.securesms.recipients.RecipientUtil) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) ProfileCipher(org.whispersystems.signalservice.api.crypto.ProfileCipher) ProfileAndCredential(org.whispersystems.signalservice.api.profiles.ProfileAndCredential) Badges(org.thoughtcrime.securesms.badges.Badges) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) Locale(java.util.Locale) Map(java.util.Map) Badge(org.thoughtcrime.securesms.badges.models.Badge) Recipient(org.thoughtcrime.securesms.recipients.Recipient) InvalidCiphertextException(org.whispersystems.signalservice.api.crypto.InvalidCiphertextException) SignalExecutors(org.signal.core.util.concurrent.SignalExecutors) UnidentifiedAccessMode(org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode) Base64(org.thoughtcrime.securesms.util.Base64) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) ProfileKeyUtil(org.thoughtcrime.securesms.crypto.ProfileKeyUtil) Set(java.util.Set) SetUtil(org.thoughtcrime.securesms.util.SetUtil) GroupDatabase(org.thoughtcrime.securesms.database.GroupDatabase) IdentityKey(org.whispersystems.libsignal.IdentityKey) Log(org.signal.core.util.logging.Log) List(java.util.List) Nullable(androidx.annotation.Nullable) ProfileService(org.whispersystems.signalservice.api.services.ProfileService) Application(android.app.Application) Job(org.thoughtcrime.securesms.jobmanager.Job) Context(android.content.Context) SignalDatabase(org.thoughtcrime.securesms.database.SignalDatabase) RetryLaterException(org.thoughtcrime.securesms.transport.RetryLaterException) Stream(com.annimon.stream.Stream) Util(org.thoughtcrime.securesms.util.Util) ProfileName(org.thoughtcrime.securesms.profiles.ProfileName) WorkerThread(androidx.annotation.WorkerThread) RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) SignalServiceProfile(org.whispersystems.signalservice.api.profiles.SignalServiceProfile) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Schedulers(io.reactivex.rxjava3.schedulers.Schedulers) Pair(org.whispersystems.libsignal.util.Pair) ProfileUtil(org.thoughtcrime.securesms.util.ProfileUtil) Observable(io.reactivex.rxjava3.core.Observable) IdentityUtil(org.thoughtcrime.securesms.util.IdentityUtil) Collectors(com.annimon.stream.Collectors) ProfileKeyCredential(org.signal.zkgroup.profiles.ProfileKeyCredential) TextUtils(android.text.TextUtils) NetworkConstraint(org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint) IOException(java.io.IOException) ServiceResponse(org.whispersystems.signalservice.internal.ServiceResponse) Optional(org.whispersystems.libsignal.util.guava.Optional) TimeUnit(java.util.concurrent.TimeUnit) Stopwatch(org.thoughtcrime.securesms.util.Stopwatch) ServiceId(org.whispersystems.signalservice.api.push.ServiceId) Collections(java.util.Collections) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) Stopwatch(org.thoughtcrime.securesms.util.Stopwatch) ProfileAndCredential(org.whispersystems.signalservice.api.profiles.ProfileAndCredential) Recipient(org.thoughtcrime.securesms.recipients.Recipient) Observable(io.reactivex.rxjava3.core.Observable) ServiceId(org.whispersystems.signalservice.api.push.ServiceId) RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) ServiceResponse(org.whispersystems.signalservice.internal.ServiceResponse) ProfileService(org.whispersystems.signalservice.api.services.ProfileService) RetryLaterException(org.thoughtcrime.securesms.transport.RetryLaterException) Pair(org.whispersystems.libsignal.util.Pair)

Example 3 with ProfileAndCredential

use of org.whispersystems.signalservice.api.profiles.ProfileAndCredential in project Signal-Android by WhisperSystems.

the class RefreshOwnProfileJob method onRun.

@Override
protected void onRun() throws Exception {
    if (!SignalStore.account().isRegistered() || TextUtils.isEmpty(SignalStore.account().getE164())) {
        Log.w(TAG, "Not yet registered!");
        return;
    }
    if (SignalStore.kbsValues().hasPin() && !SignalStore.kbsValues().hasOptedOut() && SignalStore.storageService().getLastSyncTime() == 0) {
        Log.i(TAG, "Registered with PIN but haven't completed storage sync yet.");
        return;
    }
    if (!SignalStore.registrationValues().hasUploadedProfile() && SignalStore.account().isPrimaryDevice()) {
        Log.i(TAG, "Registered but haven't uploaded profile yet.");
        return;
    }
    Recipient self = Recipient.self();
    ProfileAndCredential profileAndCredential = ProfileUtil.retrieveProfileSync(context, self, getRequestType(self), false);
    SignalServiceProfile profile = profileAndCredential.getProfile();
    setProfileName(profile.getName());
    setProfileAbout(profile.getAbout(), profile.getAboutEmoji());
    setProfileAvatar(profile.getAvatar());
    setProfileCapabilities(profile.getCapabilities());
    setProfileBadges(profile.getBadges());
    Optional<ProfileKeyCredential> profileKeyCredential = profileAndCredential.getProfileKeyCredential();
    if (profileKeyCredential.isPresent()) {
        setProfileKeyCredential(self, ProfileKeyUtil.getSelfProfileKey(), profileKeyCredential.get());
    }
}
Also used : ProfileKeyCredential(org.signal.zkgroup.profiles.ProfileKeyCredential) ProfileAndCredential(org.whispersystems.signalservice.api.profiles.ProfileAndCredential) Recipient(org.thoughtcrime.securesms.recipients.Recipient) SignalServiceProfile(org.whispersystems.signalservice.api.profiles.SignalServiceProfile)

Example 4 with ProfileAndCredential

use of org.whispersystems.signalservice.api.profiles.ProfileAndCredential in project Signal-Android by WhisperSystems.

the class ProfileUtil method getAddressForRecipient.

@WorkerThread
@NonNull
public static MobileCoinPublicAddress getAddressForRecipient(@NonNull Recipient recipient) throws IOException, PaymentsAddressException {
    ProfileKey profileKey;
    try {
        profileKey = getProfileKey(recipient);
    } catch (IOException e) {
        Log.w(TAG, "Profile key not available for " + recipient.getId());
        throw new PaymentsAddressException(PaymentsAddressException.Code.NO_PROFILE_KEY);
    }
    ProfileAndCredential profileAndCredential = ProfileUtil.retrieveProfileSync(ApplicationDependencies.getApplication(), recipient, SignalServiceProfile.RequestType.PROFILE);
    SignalServiceProfile profile = profileAndCredential.getProfile();
    byte[] encryptedPaymentsAddress = profile.getPaymentAddress();
    if (encryptedPaymentsAddress == null) {
        Log.w(TAG, "Payments not enabled for " + recipient.getId());
        throw new PaymentsAddressException(PaymentsAddressException.Code.NOT_ENABLED);
    }
    try {
        IdentityKey identityKey = new IdentityKey(Base64.decode(profileAndCredential.getProfile().getIdentityKey()), 0);
        ProfileCipher profileCipher = new ProfileCipher(profileKey);
        byte[] decrypted = profileCipher.decryptWithLength(encryptedPaymentsAddress);
        SignalServiceProtos.PaymentAddress paymentAddress = SignalServiceProtos.PaymentAddress.parseFrom(decrypted);
        byte[] bytes = MobileCoinPublicAddressProfileUtil.verifyPaymentsAddress(paymentAddress, identityKey);
        MobileCoinPublicAddress mobileCoinPublicAddress = MobileCoinPublicAddress.fromBytes(bytes);
        if (mobileCoinPublicAddress == null) {
            throw new PaymentsAddressException(PaymentsAddressException.Code.INVALID_ADDRESS);
        }
        return mobileCoinPublicAddress;
    } catch (InvalidCiphertextException | IOException e) {
        Log.w(TAG, "Could not decrypt payments address, ProfileKey may be outdated for " + recipient.getId(), e);
        throw new PaymentsAddressException(PaymentsAddressException.Code.COULD_NOT_DECRYPT);
    } catch (InvalidKeyException e) {
        Log.w(TAG, "Could not verify payments address due to bad identity key " + recipient.getId(), e);
        throw new PaymentsAddressException(PaymentsAddressException.Code.INVALID_ADDRESS_SIGNATURE);
    }
}
Also used : IdentityKey(org.whispersystems.libsignal.IdentityKey) InvalidCiphertextException(org.whispersystems.signalservice.api.crypto.InvalidCiphertextException) ProfileCipher(org.whispersystems.signalservice.api.crypto.ProfileCipher) ProfileAndCredential(org.whispersystems.signalservice.api.profiles.ProfileAndCredential) IOException(java.io.IOException) PaymentsAddressException(org.thoughtcrime.securesms.payments.PaymentsAddressException) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) SignalServiceProfile(org.whispersystems.signalservice.api.profiles.SignalServiceProfile) SignalServiceProtos(org.whispersystems.signalservice.internal.push.SignalServiceProtos) MobileCoinPublicAddress(org.thoughtcrime.securesms.payments.MobileCoinPublicAddress) WorkerThread(androidx.annotation.WorkerThread) NonNull(androidx.annotation.NonNull)

Example 5 with ProfileAndCredential

use of org.whispersystems.signalservice.api.profiles.ProfileAndCredential in project Signal-Android by signalapp.

the class DirectoryHelper method filterForUnlistedUsers.

/**
 * Users can mark themselves as 'unlisted' in CDS, meaning that even if CDS says they're
 * unregistered, they might actually be registered. We need to double-check users who we already
 * have UUIDs for. Also, we only want to bother doing this for users we have conversations for,
 * so we will also only check for users that have a thread.
 */
private static UnlistedResult filterForUnlistedUsers(@NonNull Context context, @NonNull Set<RecipientId> inactiveIds) {
    List<Recipient> possiblyUnlisted = Stream.of(inactiveIds).map(Recipient::resolved).filter(Recipient::isRegistered).filter(Recipient::hasServiceId).filter(DirectoryHelper::hasCommunicatedWith).toList();
    ProfileService profileService = new ProfileService(ApplicationDependencies.getGroupsV2Operations().getProfileOperations(), ApplicationDependencies.getSignalServiceMessageReceiver(), ApplicationDependencies.getSignalWebSocket());
    List<Observable<Pair<Recipient, ServiceResponse<ProfileAndCredential>>>> requests = Stream.of(possiblyUnlisted).map(r -> ProfileUtil.retrieveProfile(context, r, SignalServiceProfile.RequestType.PROFILE, profileService).toObservable().timeout(5, TimeUnit.SECONDS).onErrorReturn(t -> new Pair<>(r, ServiceResponse.forUnknownError(t)))).toList();
    return Observable.mergeDelayError(requests).observeOn(Schedulers.io(), true).scan(new UnlistedResult.Builder(), (builder, pair) -> {
        Recipient recipient = pair.first();
        ProfileService.ProfileResponseProcessor processor = new ProfileService.ProfileResponseProcessor(pair.second());
        if (processor.hasResult()) {
            builder.potentiallyActiveIds.add(recipient.getId());
        } else if (processor.genericIoError() || !processor.notFound()) {
            builder.retries.add(recipient.getId());
            builder.potentiallyActiveIds.add(recipient.getId());
        }
        return builder;
    }).lastOrError().map(UnlistedResult.Builder::build).blockingGet();
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) NonNull(androidx.annotation.NonNull) R(org.thoughtcrime.securesms.R) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) Manifest(android.Manifest) ProfileAndCredential(org.whispersystems.signalservice.api.profiles.ProfileAndCredential) ContactsContract(android.provider.ContactsContract) BulkOperationsHandle(org.thoughtcrime.securesms.database.RecipientDatabase.BulkOperationsHandle) RegisteredState(org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) StorageSyncHelper(org.thoughtcrime.securesms.storage.StorageSyncHelper) ContentResolver(android.content.ContentResolver) Map(java.util.Map) SignalProtocolAddress(org.whispersystems.libsignal.SignalProtocolAddress) Recipient(org.thoughtcrime.securesms.recipients.Recipient) AccountManager(android.accounts.AccountManager) ACI(org.whispersystems.signalservice.api.push.ACI) Account(android.accounts.Account) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Collection(java.util.Collection) Set(java.util.Set) SetUtil(org.thoughtcrime.securesms.util.SetUtil) Objects(java.util.Objects) Log(org.signal.core.util.logging.Log) FeatureFlags(org.thoughtcrime.securesms.util.FeatureFlags) List(java.util.List) Nullable(androidx.annotation.Nullable) StorageSyncJob(org.thoughtcrime.securesms.jobs.StorageSyncJob) ProfileService(org.whispersystems.signalservice.api.services.ProfileService) BuildConfig(org.thoughtcrime.securesms.BuildConfig) InsertResult(org.thoughtcrime.securesms.database.MessageDatabase.InsertResult) Context(android.content.Context) SignalDatabase(org.thoughtcrime.securesms.database.SignalDatabase) Stream(com.annimon.stream.Stream) Util(org.thoughtcrime.securesms.util.Util) WorkerThread(androidx.annotation.WorkerThread) RemoteException(android.os.RemoteException) RetrieveProfileJob(org.thoughtcrime.securesms.jobs.RetrieveProfileJob) RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) SignalServiceProfile(org.whispersystems.signalservice.api.profiles.SignalServiceProfile) TextSecurePreferences(org.thoughtcrime.securesms.util.TextSecurePreferences) HashSet(java.util.HashSet) Schedulers(io.reactivex.rxjava3.schedulers.Schedulers) Pair(org.whispersystems.libsignal.util.Pair) NotificationChannels(org.thoughtcrime.securesms.notifications.NotificationChannels) ProfileUtil(org.thoughtcrime.securesms.util.ProfileUtil) Calendar(java.util.Calendar) Observable(io.reactivex.rxjava3.core.Observable) RegistrationUtil(org.thoughtcrime.securesms.registration.RegistrationUtil) ContactsDatabase(org.thoughtcrime.securesms.contacts.ContactsDatabase) MultiDeviceContactUpdateJob(org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob) Cursor(android.database.Cursor) Collectors(com.annimon.stream.Collectors) Permissions(org.thoughtcrime.securesms.permissions.Permissions) UuidUtil(org.whispersystems.signalservice.api.util.UuidUtil) TextUtils(android.text.TextUtils) IOException(java.io.IOException) ServiceResponse(org.whispersystems.signalservice.internal.ServiceResponse) OperationApplicationException(android.content.OperationApplicationException) Optional(org.whispersystems.libsignal.util.guava.Optional) TimeUnit(java.util.concurrent.TimeUnit) CursorUtil(org.thoughtcrime.securesms.util.CursorUtil) IncomingJoinedMessage(org.thoughtcrime.securesms.sms.IncomingJoinedMessage) ContactAccessor(org.thoughtcrime.securesms.contacts.ContactAccessor) Stopwatch(org.thoughtcrime.securesms.util.Stopwatch) PhoneNumberFormatter(org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter) Collections(java.util.Collections) ServiceResponse(org.whispersystems.signalservice.internal.ServiceResponse) ProfileService(org.whispersystems.signalservice.api.services.ProfileService) Recipient(org.thoughtcrime.securesms.recipients.Recipient) Observable(io.reactivex.rxjava3.core.Observable)

Aggregations

ProfileAndCredential (org.whispersystems.signalservice.api.profiles.ProfileAndCredential)10 SignalServiceProfile (org.whispersystems.signalservice.api.profiles.SignalServiceProfile)10 NonNull (androidx.annotation.NonNull)6 WorkerThread (androidx.annotation.WorkerThread)6 IOException (java.io.IOException)6 TimeUnit (java.util.concurrent.TimeUnit)6 ProfileKey (org.signal.zkgroup.profiles.ProfileKey)6 ProfileKeyCredential (org.signal.zkgroup.profiles.ProfileKeyCredential)6 Recipient (org.thoughtcrime.securesms.recipients.Recipient)6 Pair (org.whispersystems.libsignal.util.Pair)6 Optional (org.whispersystems.libsignal.util.guava.Optional)6 ServiceResponse (org.whispersystems.signalservice.internal.ServiceResponse)6 Context (android.content.Context)4 TextUtils (android.text.TextUtils)4 Nullable (androidx.annotation.Nullable)4 Collectors (com.annimon.stream.Collectors)4 Stream (com.annimon.stream.Stream)4 Observable (io.reactivex.rxjava3.core.Observable)4 Schedulers (io.reactivex.rxjava3.schedulers.Schedulers)4 Collections (java.util.Collections)4