Limit the directory refresh in response to system contact changes.
Previously, we would do a full directory/CDS refresh in response to any change in system contacts. That can be expensive. This changes the behavior to look at how many new contacts there after being notified of a contact change. - If there aren't any, we just sync names and stuff. - If we just have a few new contacts, we'll sync just those specifically. - If we have a lot, we'll do a full sync.
This commit is contained in:
parent
1aa8e9753d
commit
fcc49ae7b6
2 changed files with 133 additions and 80 deletions
|
@ -7,16 +7,30 @@ import android.content.Context;
|
||||||
import android.content.SyncResult;
|
import android.content.SyncResult;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper;
|
import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper;
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
|
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.util.SetUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class ContactsSyncAdapter extends AbstractThreadedSyncAdapter {
|
public class ContactsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||||
|
|
||||||
private static final String TAG = Log.tag(ContactsSyncAdapter.class);
|
private static final String TAG = Log.tag(ContactsSyncAdapter.class);
|
||||||
|
|
||||||
|
private static final int FULL_SYNC_THRESHOLD = 10;
|
||||||
|
|
||||||
public ContactsSyncAdapter(Context context, boolean autoInitialize) {
|
public ContactsSyncAdapter(Context context, boolean autoInitialize) {
|
||||||
super(context, autoInitialize);
|
super(context, autoInitialize);
|
||||||
}
|
}
|
||||||
|
@ -27,12 +41,40 @@ public class ContactsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||||
{
|
{
|
||||||
Log.i(TAG, "onPerformSync(" + authority +")");
|
Log.i(TAG, "onPerformSync(" + authority +")");
|
||||||
|
|
||||||
if (TextSecurePreferences.isPushRegistered(getContext())) {
|
Context context = getContext();
|
||||||
|
|
||||||
|
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||||
|
Log.i(TAG, "Not push registered. Just syncing contact info.");
|
||||||
|
DirectoryHelper.syncRecipientInfoWithSystemContacts(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> allSystemNumbers = ContactAccessor.getInstance().getAllContactsWithNumbers(context);
|
||||||
|
Set<String> knownSystemNumbers = DatabaseFactory.getRecipientDatabase(context).getAllPhoneNumbers();
|
||||||
|
Set<String> unknownSystemNumbers = SetUtil.difference(allSystemNumbers, knownSystemNumbers);
|
||||||
|
|
||||||
|
if (unknownSystemNumbers.size() > FULL_SYNC_THRESHOLD) {
|
||||||
|
Log.i(TAG, "There are " + unknownSystemNumbers.size() + " unknown contacts. Doing a full sync.");
|
||||||
try {
|
try {
|
||||||
DirectoryHelper.refreshDirectory(getContext(), true);
|
DirectoryHelper.refreshDirectory(context, true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
}
|
}
|
||||||
|
} else if (unknownSystemNumbers.size() > 0) {
|
||||||
|
Log.i(TAG, "There are " + unknownSystemNumbers.size() + " unknown contacts. Doing an individual sync.");
|
||||||
|
List<Recipient> recipients = Stream.of(unknownSystemNumbers)
|
||||||
|
.filter(s -> s.startsWith("+"))
|
||||||
|
.map(s -> Recipient.external(getContext(), s))
|
||||||
|
.toList();
|
||||||
|
try {
|
||||||
|
DirectoryHelper.refreshDirectoryFor(context, recipients, true);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, "Failed to refresh! Scheduling for later.", e);
|
||||||
|
ApplicationDependencies.getJobManager().add(new DirectoryRefreshJob(true));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "No new contacts. Just syncing system contact data.");
|
||||||
|
DirectoryHelper.syncRecipientInfoWithSystemContacts(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -209,6 +209,13 @@ public class DirectoryHelper {
|
||||||
return newRegisteredState;
|
return newRegisteredState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the system contacts and copies over any matching data (like names) int our local store.
|
||||||
|
*/
|
||||||
|
public static void syncRecipientInfoWithSystemContacts(@NonNull Context context) {
|
||||||
|
syncRecipientInfoWithSystemContacts(context, Collections.emptyMap());
|
||||||
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
private static void refreshNumbers(@NonNull Context context, @NonNull Set<String> databaseNumbers, @NonNull Set<String> systemNumbers, boolean notifyOfNewUsers) throws IOException {
|
private static void refreshNumbers(@NonNull Context context, @NonNull Set<String> databaseNumbers, @NonNull Set<String> systemNumbers, boolean notifyOfNewUsers) throws IOException {
|
||||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||||
|
@ -310,7 +317,6 @@ public class DirectoryHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
|
||||||
ContactsDatabase contactsDatabase = DatabaseFactory.getContactsDatabase(context);
|
ContactsDatabase contactsDatabase = DatabaseFactory.getContactsDatabase(context);
|
||||||
List<String> activeAddresses = Stream.of(activeIds)
|
List<String> activeAddresses = Stream.of(activeIds)
|
||||||
.map(Recipient::resolved)
|
.map(Recipient::resolved)
|
||||||
|
@ -321,6 +327,14 @@ public class DirectoryHelper {
|
||||||
contactsDatabase.removeDeletedRawContacts(account.getAccount());
|
contactsDatabase.removeDeletedRawContacts(account.getAccount());
|
||||||
contactsDatabase.setRegisteredUsers(account.getAccount(), activeAddresses, removeMissing);
|
contactsDatabase.setRegisteredUsers(account.getAccount(), activeAddresses, removeMissing);
|
||||||
|
|
||||||
|
syncRecipientInfoWithSystemContacts(context, rewrites);
|
||||||
|
} catch (RemoteException | OperationApplicationException e) {
|
||||||
|
Log.w(TAG, "Failed to update contacts.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void syncRecipientInfoWithSystemContacts(@NonNull Context context, @NonNull Map<String, String> rewrites) {
|
||||||
|
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||||
BulkOperationsHandle handle = recipientDatabase.beginBulkSystemContactUpdate();
|
BulkOperationsHandle handle = recipientDatabase.beginBulkSystemContactUpdate();
|
||||||
|
|
||||||
try (Cursor cursor = ContactAccessor.getInstance().getAllSystemContacts(context)) {
|
try (Cursor cursor = ContactAccessor.getInstance().getAllSystemContacts(context)) {
|
||||||
|
@ -392,9 +406,6 @@ public class DirectoryHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RemoteException | OperationApplicationException e) {
|
|
||||||
Log.w(TAG, "Failed to update contacts.", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPhoneMimeType(@NonNull String mimeType) {
|
private static boolean isPhoneMimeType(@NonNull String mimeType) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue