mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-25 03:09:05 +00:00
Move more system contact info into recipient database
1) Move contact URI, contact photo URI, and custom label into recipient database, so there are no longer any contact DB queries during Recipient object loading. 2) Use a SoftHashMap so that any referenced Recipient objects can't get kicked out of the cache. 3) Don't load Recipient objects through the provider during sync. This was a super expensive thing to do, and blew up the cache. 4) Only apply changes to Recipient objects during sync if they are in the cache. Otherwise, there should be no outstanding references, and the changes are fine going exclusively to the DB.
This commit is contained in:
@@ -22,14 +22,21 @@ import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.annimon.stream.function.Consumer;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.GroupRecordContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.SystemContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.TransparentContactPhoto;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
@@ -42,7 +49,6 @@ import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -65,8 +71,8 @@ public class Recipient implements RecipientModifiedListener {
|
||||
private @Nullable String customLabel;
|
||||
private boolean resolving;
|
||||
|
||||
private @Nullable ContactPhoto contactPhoto;
|
||||
private @NonNull FallbackContactPhoto fallbackContactPhoto;
|
||||
private @Nullable Uri systemContactPhoto;
|
||||
private @Nullable Long groupAvatarId;
|
||||
private Uri contactUri;
|
||||
private @Nullable Uri ringtone = null;
|
||||
private long mutedUntil = 0;
|
||||
@@ -97,21 +103,25 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return provider.getRecipient(context, address, settings, groupRecord, asynchronous);
|
||||
}
|
||||
|
||||
public static void applyCached(@NonNull Address address, Consumer<Recipient> consumer) {
|
||||
Optional<Recipient> recipient = provider.getCached(address);
|
||||
if (recipient.isPresent()) consumer.accept(recipient.get());
|
||||
}
|
||||
|
||||
Recipient(@NonNull Address address,
|
||||
@Nullable Recipient stale,
|
||||
@NonNull Optional<RecipientDetails> details,
|
||||
@NonNull ListenableFutureTask<RecipientDetails> future)
|
||||
{
|
||||
this.address = address;
|
||||
this.fallbackContactPhoto = new TransparentContactPhoto();
|
||||
this.color = null;
|
||||
this.resolving = true;
|
||||
|
||||
if (stale != null) {
|
||||
this.name = stale.name;
|
||||
this.contactUri = stale.contactUri;
|
||||
this.contactPhoto = stale.contactPhoto;
|
||||
this.fallbackContactPhoto = stale.fallbackContactPhoto;
|
||||
this.systemContactPhoto = stale.systemContactPhoto;
|
||||
this.groupAvatarId = stale.groupAvatarId;
|
||||
this.color = stale.color;
|
||||
this.customLabel = stale.customLabel;
|
||||
this.ringtone = stale.ringtone;
|
||||
@@ -133,8 +143,8 @@ public class Recipient implements RecipientModifiedListener {
|
||||
|
||||
if (details.isPresent()) {
|
||||
this.name = details.get().name;
|
||||
this.contactPhoto = details.get().avatar;
|
||||
this.fallbackContactPhoto = details.get().fallbackAvatar;
|
||||
this.systemContactPhoto = details.get().systemContactPhoto;
|
||||
this.groupAvatarId = details.get().groupAvatarId;
|
||||
this.color = details.get().color;
|
||||
this.ringtone = details.get().ringtone;
|
||||
this.mutedUntil = details.get().mutedUntil;
|
||||
@@ -160,8 +170,8 @@ public class Recipient implements RecipientModifiedListener {
|
||||
synchronized (Recipient.this) {
|
||||
Recipient.this.name = result.name;
|
||||
Recipient.this.contactUri = result.contactUri;
|
||||
Recipient.this.contactPhoto = result.avatar;
|
||||
Recipient.this.fallbackContactPhoto = result.fallbackAvatar;
|
||||
Recipient.this.systemContactPhoto = result.systemContactPhoto;
|
||||
Recipient.this.groupAvatarId = result.groupAvatarId;
|
||||
Recipient.this.color = result.color;
|
||||
Recipient.this.customLabel = result.customLabel;
|
||||
Recipient.this.ringtone = result.ringtone;
|
||||
@@ -205,8 +215,8 @@ public class Recipient implements RecipientModifiedListener {
|
||||
this.address = address;
|
||||
this.contactUri = details.contactUri;
|
||||
this.name = details.name;
|
||||
this.contactPhoto = details.avatar;
|
||||
this.fallbackContactPhoto = details.fallbackAvatar;
|
||||
this.systemContactPhoto = details.systemContactPhoto;
|
||||
this.groupAvatarId = details.groupAvatarId;
|
||||
this.color = details.color;
|
||||
this.customLabel = details.customLabel;
|
||||
this.ringtone = details.ringtone;
|
||||
@@ -230,6 +240,19 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return this.contactUri;
|
||||
}
|
||||
|
||||
public void setContactUri(@Nullable Uri contactUri) {
|
||||
boolean notify = false;
|
||||
|
||||
synchronized (this) {
|
||||
if (!Util.equals(contactUri, this.contactUri)) {
|
||||
this.contactUri = contactUri;
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (notify) notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized @Nullable String getName() {
|
||||
if (this.name == null && isMmsGroupRecipient()) {
|
||||
List<String> names = new LinkedList<>();
|
||||
@@ -276,10 +299,23 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return address;
|
||||
}
|
||||
|
||||
public @Nullable String getCustomLabel() {
|
||||
public synchronized @Nullable String getCustomLabel() {
|
||||
return customLabel;
|
||||
}
|
||||
|
||||
public void setCustomLabel(@Nullable String customLabel) {
|
||||
boolean notify = false;
|
||||
|
||||
synchronized (this) {
|
||||
if (!Util.equals(customLabel, this.customLabel)) {
|
||||
this.customLabel = customLabel;
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (notify) notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized Optional<Integer> getDefaultSubscriptionId() {
|
||||
return defaultSubscriptionId;
|
||||
}
|
||||
@@ -377,19 +413,43 @@ public class Recipient implements RecipientModifiedListener {
|
||||
}
|
||||
|
||||
public synchronized @NonNull FallbackContactPhoto getFallbackContactPhoto() {
|
||||
return fallbackContactPhoto;
|
||||
if (isResolving()) return new TransparentContactPhoto();
|
||||
else if (isGroupRecipient()) return new ResourceContactPhoto(R.drawable.ic_group_white_24dp, R.drawable.ic_group_large);
|
||||
else if (!TextUtils.isEmpty(name)) return new GeneratedContactPhoto(name);
|
||||
else return new GeneratedContactPhoto("#");
|
||||
}
|
||||
|
||||
public synchronized @Nullable ContactPhoto getContactPhoto() {
|
||||
return contactPhoto;
|
||||
if (isGroupRecipient() && groupAvatarId != null) return new GroupRecordContactPhoto(address, groupAvatarId);
|
||||
else if (systemContactPhoto != null) return new SystemContactPhoto(address, systemContactPhoto, 0);
|
||||
else if (profileAvatar != null) return new ProfileContactPhoto(address, profileAvatar);
|
||||
else return null;
|
||||
}
|
||||
|
||||
public void setContactPhoto(@NonNull ContactPhoto contactPhoto) {
|
||||
public void setSystemContactPhoto(@Nullable Uri systemContactPhoto) {
|
||||
boolean notify = false;
|
||||
|
||||
synchronized (this) {
|
||||
this.contactPhoto = contactPhoto;
|
||||
if (!Util.equals(systemContactPhoto, this.systemContactPhoto)) {
|
||||
this.systemContactPhoto = systemContactPhoto;
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
if (notify) notifyListeners();
|
||||
}
|
||||
|
||||
public void setGroupAvatarId(@Nullable Long groupAvatarId) {
|
||||
boolean notify = false;
|
||||
|
||||
synchronized (this) {
|
||||
if (!Util.equals(this.groupAvatarId, groupAvatarId)) {
|
||||
this.groupAvatarId = groupAvatarId;
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (notify) notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized @Nullable Uri getRingtone() {
|
||||
|
||||
@@ -17,33 +17,21 @@
|
||||
package org.thoughtcrime.securesms.recipients;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
import android.provider.ContactsContract.PhoneLookup;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.GroupRecordContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.SystemContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.TransparentContactPhoto;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.util.LRUCache;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.SoftHashMap;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
@@ -56,25 +44,17 @@ import java.util.concurrent.ExecutorService;
|
||||
|
||||
class RecipientProvider {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = RecipientProvider.class.getSimpleName();
|
||||
|
||||
private static final RecipientCache recipientCache = new RecipientCache();
|
||||
private static final ExecutorService asyncRecipientResolver = Util.newSingleThreadedLifoExecutor();
|
||||
|
||||
private static final String[] CALLER_ID_PROJECTION = new String[] {
|
||||
PhoneLookup.DISPLAY_NAME,
|
||||
PhoneLookup.LOOKUP_KEY,
|
||||
PhoneLookup._ID,
|
||||
PhoneLookup.NUMBER,
|
||||
PhoneLookup.LABEL,
|
||||
PhoneLookup.PHOTO_URI
|
||||
};
|
||||
|
||||
private static final Map<String, RecipientDetails> STATIC_DETAILS = new HashMap<String, RecipientDetails>() {{
|
||||
put("262966", new RecipientDetails("Amazon", null, null, null, new ResourceContactPhoto(R.drawable.ic_amazon), false, null, null));
|
||||
put("262966", new RecipientDetails("Amazon", null, false, null, null));
|
||||
}};
|
||||
|
||||
@NonNull Recipient getRecipient(Context context, Address address, Optional<RecipientSettings> settings, Optional<GroupRecord> groupRecord, boolean asynchronous) {
|
||||
@NonNull Recipient getRecipient(@NonNull Context context, @NonNull Address address, @NonNull Optional<RecipientSettings> settings, @NonNull Optional<GroupRecord> groupRecord, boolean asynchronous) {
|
||||
Recipient cachedRecipient = recipientCache.get(address);
|
||||
|
||||
if (cachedRecipient != null && (asynchronous || !cachedRecipient.isResolving()) && ((!groupRecord.isPresent() && !settings.isPresent()) || !cachedRecipient.isResolving() || cachedRecipient.getName() != null)) {
|
||||
@@ -93,6 +73,10 @@ class RecipientProvider {
|
||||
return cachedRecipient;
|
||||
}
|
||||
|
||||
@NonNull Optional<Recipient> getCached(@NonNull Address address) {
|
||||
return Optional.fromNullable(recipientCache.get(address));
|
||||
}
|
||||
|
||||
private @NonNull Optional<RecipientDetails> createPrefetchedRecipientDetails(@NonNull Context context, @NonNull Address address,
|
||||
@NonNull Optional<RecipientSettings> settings,
|
||||
@NonNull Optional<GroupRecord> groupRecord)
|
||||
@@ -100,7 +84,7 @@ class RecipientProvider {
|
||||
if (address.isGroup() && settings.isPresent() && groupRecord.isPresent()) {
|
||||
return Optional.of(getGroupRecipientDetails(context, address, groupRecord, settings, true));
|
||||
} else if (!address.isGroup() && settings.isPresent()) {
|
||||
return Optional.of(new RecipientDetails(null, null, null, null, new TransparentContactPhoto(), !TextUtils.isEmpty(settings.get().getSystemDisplayName()), settings.get(), null));
|
||||
return Optional.of(new RecipientDetails(null, null, !TextUtils.isEmpty(settings.get().getSystemDisplayName()), settings.get(), null));
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
@@ -108,12 +92,7 @@ class RecipientProvider {
|
||||
|
||||
private @NonNull ListenableFutureTask<RecipientDetails> getRecipientDetailsAsync(final Context context, final @NonNull Address address, final @NonNull Optional<RecipientSettings> settings, final @NonNull Optional<GroupRecord> groupRecord)
|
||||
{
|
||||
Callable<RecipientDetails> task = new Callable<RecipientDetails>() {
|
||||
@Override
|
||||
public RecipientDetails call() throws Exception {
|
||||
return getRecipientDetailsSync(context, address, settings, groupRecord, true);
|
||||
}
|
||||
};
|
||||
Callable<RecipientDetails> task = () -> getRecipientDetailsSync(context, address, settings, groupRecord, true);
|
||||
|
||||
ListenableFutureTask<RecipientDetails> future = new ListenableFutureTask<>(task);
|
||||
asyncRecipientResolver.submit(future);
|
||||
@@ -126,53 +105,18 @@ class RecipientProvider {
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getIndividualRecipientDetails(Context context, @NonNull Address address, Optional<RecipientSettings> settings) {
|
||||
ContactPhoto contactPhoto = null;
|
||||
FallbackContactPhoto fallbackContactPhoto = new GeneratedContactPhoto("#");
|
||||
|
||||
if (!settings.isPresent()) {
|
||||
settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(address);
|
||||
}
|
||||
|
||||
if (settings.isPresent() && !TextUtils.isEmpty(settings.get().getProfileAvatar())) {
|
||||
contactPhoto = new ProfileContactPhoto(address, settings.get().getProfileAvatar());
|
||||
if (!settings.isPresent() && STATIC_DETAILS.containsKey(address.serialize())) {
|
||||
return STATIC_DETAILS.get(address.serialize());
|
||||
} else {
|
||||
return new RecipientDetails(null, null, false, settings.orNull(), null);
|
||||
}
|
||||
|
||||
if (address.isPhone() && !TextUtils.isEmpty(address.toPhoneString())) {
|
||||
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address.toPhoneString()));
|
||||
|
||||
try (Cursor cursor = context.getContentResolver().query(uri, CALLER_ID_PROJECTION, null, null, null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
final String resultNumber = cursor.getString(3);
|
||||
if (resultNumber != null) {
|
||||
Uri contactUri = Contacts.getLookupUri(cursor.getLong(2), cursor.getString(1));
|
||||
String name = resultNumber.equals(cursor.getString(0)) ? null : cursor.getString(0);
|
||||
String photoUri = cursor.getString(5);
|
||||
|
||||
if (!TextUtils.isEmpty(photoUri)) {
|
||||
contactPhoto = new SystemContactPhoto(address, Uri.parse(photoUri), 0);
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(name)) {
|
||||
fallbackContactPhoto = new GeneratedContactPhoto(name);
|
||||
}
|
||||
|
||||
return new RecipientDetails(cursor.getString(0), cursor.getString(4), contactUri, contactPhoto, fallbackContactPhoto, true, settings.orNull(), null);
|
||||
} else {
|
||||
Log.w(TAG, "resultNumber is null");
|
||||
}
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
Log.w(TAG, se);
|
||||
}
|
||||
}
|
||||
|
||||
if (STATIC_DETAILS.containsKey(address.serialize())) return STATIC_DETAILS.get(address.serialize());
|
||||
else return new RecipientDetails(null, null, null, contactPhoto, fallbackContactPhoto, false, settings.orNull(), null);
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getGroupRecipientDetails(Context context, Address groupId, Optional<GroupRecord> groupRecord, Optional<RecipientSettings> settings, boolean asynchronous) {
|
||||
ContactPhoto contactPhoto = null;
|
||||
FallbackContactPhoto fallbackContactPhoto = new ResourceContactPhoto(R.drawable.ic_group_white_24dp, R.drawable.ic_group_large);
|
||||
|
||||
if (!groupRecord.isPresent()) {
|
||||
groupRecord = DatabaseFactory.getGroupDatabase(context).getGroup(groupId.toGroupString());
|
||||
@@ -192,65 +136,59 @@ class RecipientProvider {
|
||||
}
|
||||
|
||||
if (!groupId.isMmsGroup() && title == null) {
|
||||
title = context.getString(R.string.RecipientProvider_unnamed_group);;
|
||||
title = context.getString(R.string.RecipientProvider_unnamed_group);
|
||||
}
|
||||
|
||||
if (groupRecord.get().getAvatar() != null) {
|
||||
contactPhoto = new GroupRecordContactPhoto(groupId, groupRecord.get().getAvatarId());
|
||||
}
|
||||
|
||||
return new RecipientDetails(title, null, null, contactPhoto, fallbackContactPhoto, false, settings.orNull(), members);
|
||||
return new RecipientDetails(title, groupRecord.get().getAvatarId(), false, settings.orNull(), members);
|
||||
}
|
||||
|
||||
return new RecipientDetails(context.getString(R.string.RecipientProvider_unnamed_group), null, null, contactPhoto, fallbackContactPhoto, false, settings.orNull(), null);
|
||||
return new RecipientDetails(context.getString(R.string.RecipientProvider_unnamed_group), null, false, settings.orNull(), null);
|
||||
}
|
||||
|
||||
static class RecipientDetails {
|
||||
@Nullable public final String name;
|
||||
@Nullable public final String customLabel;
|
||||
@Nullable public final ContactPhoto avatar;
|
||||
@NonNull public final FallbackContactPhoto fallbackAvatar;
|
||||
@Nullable public final Uri contactUri;
|
||||
@Nullable public final MaterialColor color;
|
||||
@Nullable public final Uri ringtone;
|
||||
public final long mutedUntil;
|
||||
@Nullable public final VibrateState vibrateState;
|
||||
public final boolean blocked;
|
||||
public final int expireMessages;
|
||||
@NonNull public final List<Recipient> participants;
|
||||
@Nullable public final String profileName;
|
||||
public final boolean seenInviteReminder;
|
||||
public final Optional<Integer> defaultSubscriptionId;
|
||||
@NonNull public final RegisteredState registered;
|
||||
@Nullable public final byte[] profileKey;
|
||||
@Nullable public final String profileAvatar;
|
||||
public final boolean profileSharing;
|
||||
public final boolean systemContact;
|
||||
@Nullable final String name;
|
||||
@Nullable final String customLabel;
|
||||
@Nullable final Uri systemContactPhoto;
|
||||
@Nullable final Uri contactUri;
|
||||
@Nullable final Long groupAvatarId;
|
||||
@Nullable final MaterialColor color;
|
||||
@Nullable final Uri ringtone;
|
||||
final long mutedUntil;
|
||||
@Nullable final VibrateState vibrateState;
|
||||
final boolean blocked;
|
||||
final int expireMessages;
|
||||
@NonNull final List<Recipient> participants;
|
||||
@Nullable final String profileName;
|
||||
final boolean seenInviteReminder;
|
||||
final Optional<Integer> defaultSubscriptionId;
|
||||
@NonNull final RegisteredState registered;
|
||||
@Nullable final byte[] profileKey;
|
||||
@Nullable final String profileAvatar;
|
||||
final boolean profileSharing;
|
||||
final boolean systemContact;
|
||||
|
||||
public RecipientDetails(@Nullable String name, @Nullable String customLabel,
|
||||
@Nullable Uri contactUri, @Nullable ContactPhoto avatar,
|
||||
@NonNull FallbackContactPhoto fallbackAvatar,
|
||||
boolean systemContact, @Nullable RecipientSettings settings,
|
||||
@Nullable List<Recipient> participants)
|
||||
RecipientDetails(@Nullable String name, @Nullable Long groupAvatarId,
|
||||
boolean systemContact, @Nullable RecipientSettings settings,
|
||||
@Nullable List<Recipient> participants)
|
||||
{
|
||||
this.customLabel = customLabel;
|
||||
this.avatar = avatar;
|
||||
this.fallbackAvatar = fallbackAvatar;
|
||||
this.contactUri = contactUri;
|
||||
this.groupAvatarId = groupAvatarId;
|
||||
this.systemContactPhoto = settings != null ? Util.uri(settings.getSystemContactPhotoUri()) : null;
|
||||
this.customLabel = settings != null ? settings.getSystemPhoneLabel() : null;
|
||||
this.contactUri = settings != null ? Util.uri(settings.getSystemContactUri()) : null;
|
||||
this.color = settings != null ? settings.getColor() : null;
|
||||
this.ringtone = settings != null ? settings.getRingtone() : null;
|
||||
this.mutedUntil = settings != null ? settings.getMuteUntil() : 0;
|
||||
this.vibrateState = settings != null ? settings.getVibrateState() : null;
|
||||
this.blocked = settings != null && settings.isBlocked();
|
||||
this.blocked = settings != null && settings.isBlocked();
|
||||
this.expireMessages = settings != null ? settings.getExpireMessages() : 0;
|
||||
this.participants = participants == null ? new LinkedList<Recipient>() : participants;
|
||||
this.participants = participants == null ? new LinkedList<>() : participants;
|
||||
this.profileName = settings != null ? settings.getProfileName() : null;
|
||||
this.seenInviteReminder = settings != null && settings.hasSeenInviteReminder();
|
||||
this.seenInviteReminder = settings != null && settings.hasSeenInviteReminder();
|
||||
this.defaultSubscriptionId = settings != null ? settings.getDefaultSubscriptionId() : Optional.absent();
|
||||
this.registered = settings != null ? settings.getRegistered() : RegisteredState.UNKNOWN;
|
||||
this.profileKey = settings != null ? settings.getProfileKey() : null;
|
||||
this.profileAvatar = settings != null ? settings.getProfileAvatar() : null;
|
||||
this.profileSharing = settings != null && settings.isProfileSharing();
|
||||
this.profileSharing = settings != null && settings.isProfileSharing();
|
||||
this.systemContact = systemContact;
|
||||
|
||||
if (name == null && settings != null) this.name = settings.getSystemDisplayName();
|
||||
@@ -260,7 +198,7 @@ class RecipientProvider {
|
||||
|
||||
private static class RecipientCache {
|
||||
|
||||
private final Map<Address,Recipient> cache = new LRUCache<>(1000);
|
||||
private final Map<Address,Recipient> cache = new SoftHashMap<>(1000);
|
||||
|
||||
public synchronized Recipient get(Address address) {
|
||||
return cache.get(address);
|
||||
|
||||
Reference in New Issue
Block a user