use of androidx.annotation.AnyThread in project Signal-Android by signalapp.
the class BlobProvider method initialize.
/**
* Allows the class to be initialized. Part of this initialization is deleting any leftover
* single-session blobs from the previous session. However, this class defers that work to a
* background thread, so callers don't have to worry about it.
*/
@AnyThread
public synchronized void initialize(@NonNull Context context) {
SignalExecutors.BOUNDED.execute(() -> {
synchronized (this) {
File directory = getOrCreateDirectory(context, SINGLE_SESSION_DIRECTORY);
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.delete()) {
Log.d(TAG, "Deleted single-session file: " + file.getName());
} else {
Log.w(TAG, "Failed to delete single-session file! " + file.getName());
}
}
} else {
Log.w(TAG, "Null directory listing!");
}
deleteOrphanedDraftFiles(context);
Log.i(TAG, "Initialized.");
initialized = true;
notifyAll();
}
});
}
use of androidx.annotation.AnyThread in project Signal-Android by signalapp.
the class MegaphoneRepository method markSeen.
@AnyThread
public void markSeen(@NonNull Event event) {
long lastSeen = System.currentTimeMillis();
executor.execute(() -> {
MegaphoneRecord record = getRecord(event);
database.markSeen(event, record.getSeenCount() + 1, lastSeen);
enabled = false;
resetDatabaseCache();
});
}
use of androidx.annotation.AnyThread in project Signal-Android by signalapp.
the class LiveRecipientCache method addToCache.
/**
* Adds a recipient to the cache if we don't have an entry. This will also update a cache entry
* if the provided recipient is resolved, or if the existing cache entry is unresolved.
*
* If the recipient you add is unresolved, this will enqueue a resolve on a background thread.
*/
@AnyThread
public void addToCache(@NonNull Collection<Recipient> newRecipients) {
newRecipients.stream().filter(this::isValidForCache).forEach(recipient -> {
LiveRecipient live;
boolean needsResolve;
synchronized (recipients) {
live = recipients.get(recipient.getId());
if (live == null) {
live = new LiveRecipient(context, recipient);
recipients.put(recipient.getId(), live);
needsResolve = recipient.isResolving();
} else if (live.get().isResolving() || !recipient.isResolving()) {
live.set(recipient);
needsResolve = recipient.isResolving();
} else {
needsResolve = false;
}
}
if (needsResolve) {
LiveRecipient toResolve = live;
MissingRecipientException prettyStackTraceError = new MissingRecipientException(toResolve.getId());
resolveExecutor.execute(() -> {
try {
toResolve.resolve();
} catch (MissingRecipientException e) {
throw prettyStackTraceError;
}
});
}
});
}
use of androidx.annotation.AnyThread in project Signal-Android by signalapp.
the class LiveRecipientCache method warmUp.
@AnyThread
public void warmUp() {
if (warmedUp.getAndSet(true)) {
return;
}
Stopwatch stopwatch = new Stopwatch("recipient-warm-up");
SignalExecutors.BOUNDED.execute(() -> {
ThreadDatabase threadDatabase = SignalDatabase.threads();
List<Recipient> recipients = new ArrayList<>();
try (ThreadDatabase.Reader reader = threadDatabase.readerFor(threadDatabase.getRecentConversationList(THREAD_CACHE_WARM_MAX, false, false))) {
int i = 0;
ThreadRecord record = null;
while ((record = reader.getNext()) != null && i < THREAD_CACHE_WARM_MAX) {
recipients.add(record.getRecipient());
i++;
}
}
Log.d(TAG, "Warming up " + recipients.size() + " thread recipients.");
addToCache(recipients);
stopwatch.split("thread");
if (SignalStore.registrationValues().isRegistrationComplete() && SignalStore.account().getAci() != null) {
try (Cursor cursor = SignalDatabase.recipients().getNonGroupContacts(false)) {
int count = 0;
while (cursor != null && cursor.moveToNext() && count < CONTACT_CACHE_WARM_MAX) {
RecipientId id = RecipientId.from(CursorUtil.requireLong(cursor, RecipientDatabase.ID));
Recipient.resolved(id);
count++;
}
Log.d(TAG, "Warmed up " + count + " contact recipient.");
stopwatch.split("contact");
}
}
stopwatch.stop(TAG);
});
}
use of androidx.annotation.AnyThread in project Signal-Android by signalapp.
the class SimpleProgressDialog method showDelayed.
/**
* Shows the dialog after {@param delayMs} ms.
* <p>
* To dismiss, call {@link DismissibleDialog#dismiss()} on the result. If dismiss is called before
* the delay has elapsed, the dialog will not show at all.
* <p>
* Dismiss can be called on any thread.
*
* @param minimumShowTimeMs If the dialog does display, then it will be visible for at least this duration.
* This is to prevent flicker.
*/
@AnyThread
@NonNull
public static DismissibleDialog showDelayed(@NonNull Context context, int delayMs, int minimumShowTimeMs) {
AtomicReference<AlertDialog> dialogAtomicReference = new AtomicReference<>();
AtomicLong shownAt = new AtomicLong();
Runnable showRunnable = () -> {
Log.i(TAG, "Taking some time. Showing a progress dialog.");
shownAt.set(System.currentTimeMillis());
dialogAtomicReference.set(show(context));
};
ThreadUtil.runOnMainDelayed(showRunnable, delayMs);
return new DismissibleDialog() {
@Override
public void dismiss() {
ThreadUtil.cancelRunnableOnMain(showRunnable);
ThreadUtil.runOnMain(() -> {
AlertDialog alertDialog = dialogAtomicReference.getAndSet(null);
if (alertDialog != null) {
long beenShowingForMs = System.currentTimeMillis() - shownAt.get();
long remainingTimeMs = minimumShowTimeMs - beenShowingForMs;
if (remainingTimeMs > 0) {
ThreadUtil.runOnMainDelayed(alertDialog::dismiss, remainingTimeMs);
} else {
alertDialog.dismiss();
}
}
});
}
@Override
public void dismissNow() {
ThreadUtil.cancelRunnableOnMain(showRunnable);
ThreadUtil.runOnMain(() -> {
AlertDialog alertDialog = dialogAtomicReference.getAndSet(null);
if (alertDialog != null) {
alertDialog.dismiss();
}
});
}
};
}
Aggregations