Don't invalidate entire recipient cache when contact data changes

fork-5.53.8
Moxie Marlinspike 2017-11-20 14:48:39 -08:00
rodzic 8f6440ce17
commit 66e1be1aeb
9 zmienionych plików z 92 dodań i 198 usunięć

Wyświetl plik

@ -105,7 +105,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.DraftDatabase;
import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
import org.thoughtcrime.securesms.database.DraftDatabase.Drafts;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
@ -235,7 +234,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private AttachmentManager attachmentManager;
private AudioRecorder audioRecorder;
private BroadcastReceiver securityUpdateReceiver;
private BroadcastReceiver recipientsStaleReceiver;
private Stub<EmojiDrawer> emojiDrawerStub;
protected HidingLinearLayout quickAttachmentToggle;
private QuickAttachmentDrawer quickAttachmentDrawer;
@ -386,7 +384,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
saveDraft();
if (recipient != null) recipient.removeListener(this);
if (securityUpdateReceiver != null) unregisterReceiver(securityUpdateReceiver);
if (recipientsStaleReceiver != null) unregisterReceiver(recipientsStaleReceiver);
super.onDestroy();
}
@ -1345,29 +1342,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
};
recipientsStaleReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.w(TAG, "Group update received...");
if (recipient != null) {
Log.w(TAG, "Looking up new recipients...");
recipient = Recipient.from(context, recipient.getAddress(), true);
recipient.addListener(ConversationActivity.this);
onModified(recipient);
fragment.reloadList();
}
}
};
IntentFilter staleFilter = new IntentFilter();
staleFilter.addAction(GroupDatabase.DATABASE_UPDATE_ACTION);
staleFilter.addAction(Recipient.RECIPIENT_CLEAR_ACTION);
registerReceiver(securityUpdateReceiver,
new IntentFilter(SecurityEvent.SECURITY_UPDATE_EVENT),
KeyCachingService.KEY_PERMISSION, null);
registerReceiver(recipientsStaleReceiver, staleFilter);
}
//////// Helper Methods

Wyświetl plik

@ -20,14 +20,11 @@ import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@ -53,13 +50,13 @@ import java.util.List;
public class ConversationListActivity extends PassphraseRequiredActionBarActivity
implements ConversationListFragment.ConversationSelectedListener
{
@SuppressWarnings("unused")
private static final String TAG = ConversationListActivity.class.getSimpleName();
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private ConversationListFragment fragment;
private ContentObserver observer;
private MasterSecret masterSecret;
private SearchToolbar searchToolbar;
private ImageView searchAction;
@ -83,7 +80,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
searchAction = findViewById(R.id.search_action);
fragment = initFragment(R.id.fragment_container, new ConversationListFragment(), masterSecret, dynamicLanguage.getCurrentLocale());
initializeContactUpdatesReceiver();
initializeSearchListener();
RatingManager.showRatingDialogIfNecessary(this);
@ -98,7 +94,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
@Override
public void onDestroy() {
if (observer != null) getContentResolver().unregisterContentObserver(observer);
super.onDestroy();
}
@ -225,19 +220,4 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
Toast.makeText(this, R.string.ConversationListActivity_there_is_no_browser_installed_on_your_device, Toast.LENGTH_LONG).show();
}
}
private void initializeContactUpdatesReceiver() {
observer = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.w(TAG, "Detected android contact data changed, refreshing cache");
Recipient.clearCache(ConversationListActivity.this);
ConversationListActivity.this.runOnUiThread(() -> fragment.getListAdapter().notifyDataSetChanged());
}
};
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI,
true, observer);
}
}

Wyświetl plik

@ -4,7 +4,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.graphics.Color;
import android.media.Ringtone;
@ -42,7 +41,6 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
import org.thoughtcrime.securesms.database.RecipientDatabase;
@ -93,7 +91,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
private TextView threadPhotoRailLabel;
private ThreadPhotoRailView threadPhotoRailView;
private CollapsingToolbarLayout toolbarLayout;
private BroadcastReceiver staleReceiver;
@Override
public void onPreCreate() {
@ -111,7 +108,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
Recipient recipient = Recipient.from(this, address, true);
initializeToolbar();
initializeReceivers();
setHeader(recipient);
recipient.addListener(this);
@ -125,12 +121,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
dynamicLanguage.onResume(this);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(staleReceiver);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
@ -192,23 +182,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
}
}
private void initializeReceivers() {
this.staleReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Recipient recipient = Recipient.from(context, (Address)getIntent().getParcelableExtra(ADDRESS_EXTRA), true);
recipient.addListener(RecipientPreferenceActivity.this);
onModified(recipient);
}
};
IntentFilter staleFilter = new IntentFilter();
staleFilter.addAction(GroupDatabase.DATABASE_UPDATE_ACTION);
staleFilter.addAction(Recipient.RECIPIENT_CLEAR_ACTION);
registerReceiver(staleReceiver, staleFilter);
}
private void setHeader(@NonNull Recipient recipient) {
glideRequests.load(recipient.getContactPhoto())
.fallback(recipient.getFallbackContactPhoto().asCallCard(this))
@ -306,23 +279,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
private void initializeRecipients() {
this.recipient = Recipient.from(getActivity(), getArguments().getParcelable(ADDRESS_EXTRA), true);
this.recipient.addListener(this);
this.staleReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
recipient.removeListener(RecipientPreferenceFragment.this);
recipient = Recipient.from(getActivity(), getArguments().getParcelable(ADDRESS_EXTRA), true);
onModified(recipient);
}
};
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(GroupDatabase.DATABASE_UPDATE_ACTION);
intentFilter.addAction(Recipient.RECIPIENT_CLEAR_ACTION);
getActivity().registerReceiver(staleReceiver, intentFilter);
}
private void setSummaries(Recipient recipient) {

Wyświetl plik

@ -38,14 +38,10 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -80,13 +76,12 @@ public class ContactsDatabase {
this.context = context;
}
public synchronized @NonNull List<Address> setRegisteredUsers(@NonNull Account account,
@NonNull List<Address> registeredAddressList,
boolean remove)
public synchronized void setRegisteredUsers(@NonNull Account account,
@NonNull List<Address> registeredAddressList,
boolean remove)
throws RemoteException, OperationApplicationException
{
Set<Address> registeredAddressSet = new HashSet<>();
List<Address> addedAddresses = new LinkedList<>();
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
Map<Address, SignalContact> currentContacts = getSignalRawContacts(account);
@ -98,7 +93,6 @@ public class ContactsDatabase {
if (systemContactInfo.isPresent()) {
Log.w(TAG, "Adding number: " + registeredAddress);
addedAddresses.add(registeredAddress);
addTextSecureRawContact(operations, account, systemContactInfo.get().number,
systemContactInfo.get().name, systemContactInfo.get().id,
true);
@ -126,8 +120,6 @@ public class ContactsDatabase {
if (!operations.isEmpty()) {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
}
return addedAddresses;
}
@NonNull Cursor querySystemContacts(@Nullable String filter) {

Wyświetl plik

@ -1,9 +1,9 @@
package org.thoughtcrime.securesms.database;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
@ -14,6 +14,7 @@ import android.text.TextUtils;
import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.contacts.avatars.GroupRecordContactPhoto;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
@ -30,8 +31,7 @@ import java.util.List;
public class GroupDatabase extends Database {
public static final String DATABASE_UPDATE_ACTION = "org.thoughtcrime.securesms.database.GroupDatabase.UPDATE";
@SuppressWarnings("unused")
private static final String TAG = GroupDatabase.class.getSimpleName();
static final String TABLE_NAME = "groups";
@ -65,7 +65,7 @@ public class GroupDatabase extends Database {
AVATAR_DIGEST + " BLOB, " +
MMS + " INTEGER DEFAULT 0);";
public static final String[] CREATE_INDEXS = {
static final String[] CREATE_INDEXS = {
"CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON " + TABLE_NAME + " (" + GROUP_ID + ");",
};
@ -103,9 +103,10 @@ public class GroupDatabase extends Database {
}
public Reader getGroupsFilteredByTitle(String constraint) {
@SuppressLint("Recycle")
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, TITLE + " LIKE ?",
new String[]{"%" + constraint + "%"},
null, null, null);
new String[]{"%" + constraint + "%"},
null, null, null);
return new Reader(cursor);
}
@ -131,6 +132,7 @@ public class GroupDatabase extends Database {
}
public Reader getGroups() {
@SuppressLint("Recycle")
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, null, null, null, null, null);
return new Reader(cursor);
}
@ -172,7 +174,14 @@ public class GroupDatabase extends Database {
contentValues.put(MMS, GroupUtil.isMmsGroup(groupId));
databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
Recipient.clearCache(context);
Address address = Address.fromSerialized(groupId);
Recipient recipient = Recipient.from(context, Address.fromSerialized(groupId), false);
recipient.setName(title);
if (avatar != null) recipient.setContactPhoto(new GroupRecordContactPhoto(address, avatar.getId()));
recipient.setParticipants(Stream.of(members).map(memberAddress -> Recipient.from(context, memberAddress, true)).toList());
notifyConversationListListeners();
}
@ -191,8 +200,11 @@ public class GroupDatabase extends Database {
GROUP_ID + " = ?",
new String[] {groupId});
Recipient.clearCache(context);
notifyDatabaseListeners();
Address address = Address.fromSerialized(groupId);
Recipient recipient = Recipient.from(context, address, false);
recipient.setName(title);
if (avatar != null) recipient.setContactPhoto(new GroupRecordContactPhoto(address, avatar.getId()));
notifyConversationListListeners();
}
@ -202,8 +214,8 @@ public class GroupDatabase extends Database {
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
new String[] {groupId});
Recipient.clearCache(context);
notifyDatabaseListeners();
Recipient recipient = Recipient.from(context, Address.fromSerialized(groupId), false);
recipient.setName(title);
}
public void updateAvatar(String groupId, Bitmap avatar) {
@ -211,14 +223,17 @@ public class GroupDatabase extends Database {
}
public void updateAvatar(String groupId, byte[] avatar) {
long avatarId = Math.abs(new SecureRandom().nextLong());
ContentValues contentValues = new ContentValues();
contentValues.put(AVATAR, avatar);
contentValues.put(AVATAR_ID, avatarId);
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
new String[] {groupId});
Recipient.clearCache(context);
notifyDatabaseListeners();
Address address = Address.fromSerialized(groupId);
Recipient recipient = Recipient.from(context, address, false);
recipient.setContactPhoto(new GroupRecordContactPhoto(address, avatarId));
}
public void updateMembers(String groupId, List<Address> members) {
@ -287,11 +302,6 @@ public class GroupDatabase extends Database {
}
}
private void notifyDatabaseListeners() {
Intent intent = new Intent(DATABASE_UPDATE_ACTION);
context.sendBroadcast(intent);
}
public static class Reader {
private final Cursor cursor;

Wyświetl plik

@ -399,7 +399,7 @@ public class RecipientDatabase extends Database {
database.setTransactionSuccessful();
database.endTransaction();
Stream.of(pendingDisplayNames).forEach(pair -> pair.first().resolve().setSystemDisplayName(pair.second()));
Stream.of(pendingDisplayNames).forEach(pair -> pair.first().resolve().setName(pair.second()));
context.getContentResolver().notifyChange(Uri.parse(RECIPIENT_PREFERENCES_URI), null);
}

Wyświetl plik

@ -1,5 +1,6 @@
/**
/*
* Copyright (C) 2011 Whisper Systems
* Copyright (C) 2013 - 2017 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,7 +18,6 @@
package org.thoughtcrime.securesms.recipients;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.NonNull;
@ -50,9 +50,8 @@ import java.util.concurrent.ExecutionException;
public class Recipient implements RecipientModifiedListener {
public static final String RECIPIENT_CLEAR_ACTION = "org.thoughtcrime.securesms.database.RecipientFactory.CLEAR";
private static final String TAG = Recipient.class.getSimpleName();
private static final RecipientProvider provider = new RecipientProvider();
private static final String TAG = Recipient.class.getSimpleName();
private static final RecipientProvider provider = new RecipientProvider();
private final Set<RecipientModifiedListener> listeners = Collections.newSetFromMap(new WeakHashMap<RecipientModifiedListener, Boolean>());
@ -61,7 +60,6 @@ public class Recipient implements RecipientModifiedListener {
private @Nullable String name;
private @Nullable String customLabel;
private boolean stale;
private boolean resolving;
private @Nullable ContactPhoto contactPhoto;
@ -84,21 +82,18 @@ public class Recipient implements RecipientModifiedListener {
private boolean isSystemContact;
@SuppressWarnings("ConstantConditions")
public static @NonNull Recipient from(@NonNull Context context, @NonNull Address address, boolean asynchronous) {
if (address == null) throw new AssertionError(address);
return provider.getRecipient(context, address, Optional.absent(), Optional.absent(), asynchronous);
}
@SuppressWarnings("ConstantConditions")
public static @NonNull Recipient from(@NonNull Context context, @NonNull Address address, @NonNull Optional<RecipientSettings> settings, @NonNull Optional<GroupDatabase.GroupRecord> groupRecord, boolean asynchronous) {
if (address == null) throw new AssertionError(address);
return provider.getRecipient(context, address, settings, groupRecord, asynchronous);
}
public static void clearCache(Context context) {
provider.clearCache();
context.sendBroadcast(new Intent(RECIPIENT_CLEAR_ACTION));
}
Recipient(@NonNull Address address,
@Nullable Recipient stale,
@NonNull Optional<RecipientDetails> details,
@ -246,6 +241,19 @@ public class Recipient implements RecipientModifiedListener {
return this.name;
}
public void setName(@Nullable String name) {
boolean notify = false;
synchronized (this) {
if (!Util.equals(this.name, name)) {
this.name = name;
notify = true;
}
}
if (notify) notifyListeners();
}
public synchronized @NonNull MaterialColor getColor() {
if (isGroupRecipient()) return MaterialColor.GROUP;
else if (color != null) return color;
@ -333,6 +341,15 @@ public class Recipient implements RecipientModifiedListener {
return participants;
}
public void setParticipants(@NonNull List<Recipient> participants) {
synchronized (this) {
this.participants.clear();
this.participants.addAll(participants);
}
notifyListeners();
}
public synchronized void addListener(RecipientModifiedListener listener) {
if (listeners.isEmpty()) {
for (Recipient recipient : participants) recipient.addListener(this);
@ -452,11 +469,16 @@ public class Recipient implements RecipientModifiedListener {
}
public void setRegistered(@NonNull RegisteredState value) {
boolean notify = false;
synchronized (this) {
this.registered = value;
if (this.registered != value) {
this.registered = value;
notify = true;
}
}
notifyListeners();
if (notify) notifyListeners();
}
public synchronized @Nullable byte[] getProfileKey() {
@ -475,15 +497,6 @@ public class Recipient implements RecipientModifiedListener {
return isSystemContact;
}
public void setSystemDisplayName(@Nullable String displayName) {
synchronized (this) {
if (displayName == null) this.name = profileName;
else this.name = displayName;
}
notifyListeners();
}
public synchronized Recipient resolve() {
while (resolving) Util.wait(this, 0);
return this;
@ -521,15 +534,6 @@ public class Recipient implements RecipientModifiedListener {
notifyListeners();
}
boolean isStale() {
return stale;
}
void setStale() {
this.stale = true;
}
// XXX This shouldn't be public, temporary workaround
public synchronized boolean isResolving() {
return resolving;
}

Wyświetl plik

@ -77,7 +77,7 @@ class RecipientProvider {
@NonNull Recipient getRecipient(Context context, Address address, Optional<RecipientSettings> settings, Optional<GroupRecord> groupRecord, boolean asynchronous) {
Recipient cachedRecipient = recipientCache.get(address);
if (cachedRecipient != null && !cachedRecipient.isStale() && (asynchronous || !cachedRecipient.isResolving()) && ((!groupRecord.isPresent() && !settings.isPresent()) || !cachedRecipient.isResolving() || cachedRecipient.getName() != null)) {
if (cachedRecipient != null && (asynchronous || !cachedRecipient.isResolving()) && ((!groupRecord.isPresent() && !settings.isPresent()) || !cachedRecipient.isResolving() || cachedRecipient.getName() != null)) {
return cachedRecipient;
}
@ -93,10 +93,6 @@ class RecipientProvider {
return cachedRecipient;
}
void clearCache() {
recipientCache.reset();
}
private @NonNull Optional<RecipientDetails> createPrefetchedRecipientDetails(@NonNull Context context, @NonNull Address address,
@NonNull Optional<RecipientSettings> settings,
@NonNull Optional<GroupRecord> groupRecord)
@ -276,12 +272,6 @@ class RecipientProvider {
cache.put(address, recipient);
}
public synchronized void reset() {
for (Recipient recipient : cache.values()) {
recipient.setStale();
}
}
}
}

Wyświetl plik

@ -25,7 +25,6 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
@ -38,6 +37,7 @@ import org.whispersystems.signalservice.api.push.ContactTokenDetails;
import java.io.IOException;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@ -52,24 +52,22 @@ public class DirectoryHelper {
{
if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) return;
RefreshResult result = refreshDirectory(context, AccountManagerFactory.createManager(context));
List<Address> newlyActiveUsers = refreshDirectory(context, AccountManagerFactory.createManager(context));
if (!result.getNewUsers().isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
if (!newlyActiveUsers.isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
ApplicationContext.getInstance(context)
.getJobManager()
.add(new MultiDeviceContactUpdateJob(context));
}
if (!result.isFresh()) {
notifyNewUsers(context, masterSecret, result.getNewUsers());
}
notifyNewUsers(context, masterSecret, newlyActiveUsers);
}
public static @NonNull RefreshResult refreshDirectory(@NonNull Context context, @NonNull SignalServiceAccountManager accountManager)
public static @NonNull List<Address> refreshDirectory(@NonNull Context context, @NonNull SignalServiceAccountManager accountManager)
throws IOException
{
if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) {
return new RefreshResult(new LinkedList<>(), false);
return new LinkedList<>();
}
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
@ -94,11 +92,19 @@ public class DirectoryHelper {
inactiveRecipients.add(Recipient.from(context, Address.fromSerialized(inactiveContactNumber), true));
}
Set<Address> currentActiveAddresses = new HashSet<>(recipientDatabase.getRegistered());
List<Address> newlyActiveAddresses = Stream.of(activeRecipients)
.map(Recipient::getAddress)
.filter(address -> !currentActiveAddresses.contains(address))
.toList();
recipientDatabase.setRegistered(activeRecipients, inactiveRecipients);
return updateContactsDatabase(context, Stream.of(activeRecipients).map(Recipient::getAddress).toList(), true);
updateContactsDatabase(context, Stream.of(activeRecipients).map(Recipient::getAddress).toList(), true);
return newlyActiveAddresses;
}
return new RefreshResult(new LinkedList<>(), false);
return new LinkedList<>();
}
public static RegisteredState refreshDirectoryFor(@NonNull Context context,
@ -108,20 +114,21 @@ public class DirectoryHelper {
{
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context);
boolean activeUser = recipient.resolve().getRegistered() == RegisteredState.REGISTERED;
String number = recipient.getAddress().serialize();
Optional<ContactTokenDetails> details = accountManager.getContact(number);
if (details.isPresent()) {
recipientDatabase.setRegistered(recipient, RegisteredState.REGISTERED);
RefreshResult result = updateContactsDatabase(context, Util.asList(recipient.getAddress()), false);
updateContactsDatabase(context, Util.asList(recipient.getAddress()), false);
if (!result.getNewUsers().isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
if (!activeUser && TextSecurePreferences.isMultiDevice(context)) {
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceContactUpdateJob(context));
}
if (!result.isFresh()) {
notifyNewUsers(context, masterSecret, result.getNewUsers());
if (!activeUser) {
notifyNewUsers(context, masterSecret, Collections.singletonList(recipient.getAddress()));
}
return RegisteredState.REGISTERED;
@ -131,13 +138,12 @@ public class DirectoryHelper {
}
}
private static @NonNull RefreshResult updateContactsDatabase(@NonNull Context context, @NonNull List<Address> activeAddresses, boolean removeMissing) {
private static void updateContactsDatabase(@NonNull Context context, @NonNull List<Address> activeAddresses, boolean removeMissing) {
Optional<AccountHolder> account = getOrCreateAccount(context);
if (account.isPresent()) {
try {
List<Address> newUsers = DatabaseFactory.getContactsDatabase(context)
.setRegisteredUsers(account.get().getAccount(), activeAddresses, removeMissing);
DatabaseFactory.getContactsDatabase(context).setRegisteredUsers(account.get().getAccount(), activeAddresses, removeMissing);
Cursor cursor = ContactAccessor.getInstance().getAllSystemContacts(context);
RecipientDatabase.BulkOperationsHandle handle = DatabaseFactory.getRecipientDatabase(context).resetAllDisplayNames();
@ -158,13 +164,10 @@ public class DirectoryHelper {
handle.finish();
}
return new RefreshResult(newUsers, account.get().isFresh());
} catch (RemoteException | OperationApplicationException e) {
Log.w(TAG, e);
}
}
return new RefreshResult(new LinkedList<Address>(), false);
}
private static void notifyNewUsers(@NonNull Context context,
@ -240,23 +243,4 @@ public class DirectoryHelper {
}
private static class RefreshResult {
private final List<Address> newUsers;
private final boolean fresh;
private RefreshResult(List<Address> newUsers, boolean fresh) {
this.newUsers = newUsers;
this.fresh = fresh;
}
public List<Address> getNewUsers() {
return newUsers;
}
public boolean isFresh() {
return fresh;
}
}
}