diff --git a/app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java b/app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java index 28ef89f9e..b7b6a4811 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java @@ -18,6 +18,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; @@ -28,7 +29,6 @@ import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.InvalidKeyException; @@ -123,7 +123,7 @@ public class DeviceActivity extends PassphraseRequiredActivity @Override public void onQrDataFound(final String data) { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { ((Vibrator)getSystemService(Context.VIBRATOR_SERVICE)).vibrate(50); Uri uri = Uri.parse(data); deviceLinkFragment.setLinkClickedListener(uri, DeviceActivity.this); diff --git a/app/src/main/java/org/thoughtcrime/securesms/VerifyIdentityActivity.java b/app/src/main/java/org/thoughtcrime/securesms/VerifyIdentityActivity.java index e864f636d..435e474f0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/VerifyIdentityActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/VerifyIdentityActivity.java @@ -60,6 +60,7 @@ import androidx.appcompat.widget.SwitchCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.color.MaterialColor; @@ -185,7 +186,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActivity implement @Override public void onQrDataFound(final String data) { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { ((Vibrator)getSystemService(Context.VIBRATOR_SERVICE)).vibrate(50); getSupportFragmentManager().popBackStack(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorder.java b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorder.java index f2c599595..caed6f337 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorder.java @@ -8,11 +8,11 @@ import android.os.ParcelFileDescriptor; import androidx.annotation.NonNull; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.util.MediaUtil; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.SettableFuture; import org.whispersystems.libsignal.util.Pair; @@ -90,10 +90,10 @@ public class AudioRecorder { } private void sendToFuture(final SettableFuture future, final Exception exception) { - Util.runOnMain(() -> future.setException(exception)); + ThreadUtil.runOnMain(() -> future.setException(exception)); } private void sendToFuture(final SettableFuture future, final T result) { - Util.runOnMain(() -> future.set(result)); + ThreadUtil.runOnMain(() -> future.set(result)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioWaveForm.java b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioWaveForm.java index 2a3814e52..3e32b7e6e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioWaveForm.java +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioWaveForm.java @@ -16,6 +16,7 @@ import androidx.core.util.Consumer; import com.google.protobuf.ByteString; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.attachments.Attachment; @@ -26,7 +27,6 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.AudioWaveFormDat import org.thoughtcrime.securesms.media.DecryptableUriMediaInput; import org.thoughtcrime.securesms.media.MediaInput; import org.thoughtcrime.securesms.mms.AudioSlide; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.concurrent.SerialExecutor; import java.io.IOException; @@ -61,13 +61,13 @@ public final class AudioWaveForm { if (uri == null) { Log.w(TAG, "No uri"); - Util.runOnMain(onFailure); + ThreadUtil.runOnMain(onFailure); return; } if (!(attachment instanceof DatabaseAttachment)) { Log.i(TAG, "Not yet in database"); - Util.runOnMain(onFailure); + ThreadUtil.runOnMain(onFailure); return; } @@ -75,7 +75,7 @@ public final class AudioWaveForm { AudioFileInfo cached = WAVE_FORM_CACHE.get(cacheKey); if (cached != null) { Log.i(TAG, "Loaded wave form from cache " + cacheKey); - Util.runOnMain(() -> onSuccess.accept(cached)); + ThreadUtil.runOnMain(() -> onSuccess.accept(cached)); return; } @@ -83,7 +83,7 @@ public final class AudioWaveForm { AudioFileInfo cachedInExecutor = WAVE_FORM_CACHE.get(cacheKey); if (cachedInExecutor != null) { Log.i(TAG, "Loaded wave form from cache inside executor" + cacheKey); - Util.runOnMain(() -> onSuccess.accept(cachedInExecutor)); + ThreadUtil.runOnMain(() -> onSuccess.accept(cachedInExecutor)); return; } @@ -92,14 +92,14 @@ public final class AudioWaveForm { AudioFileInfo audioFileInfo = AudioFileInfo.fromDatabaseProtobuf(audioHash.getAudioWaveForm()); if (audioFileInfo.waveForm.length == 0) { Log.w(TAG, "Recovering from a wave form generation error " + cacheKey); - Util.runOnMain(onFailure); + ThreadUtil.runOnMain(onFailure); return; } else if (audioFileInfo.waveForm.length != BAR_COUNT) { Log.w(TAG, "Wave form from database does not match bar count, regenerating " + cacheKey); } else { WAVE_FORM_CACHE.put(cacheKey, audioFileInfo); Log.i(TAG, "Loaded wave form from DB " + cacheKey); - Util.runOnMain(() -> onSuccess.accept(audioFileInfo)); + ThreadUtil.runOnMain(() -> onSuccess.accept(audioFileInfo)); return; } } @@ -120,10 +120,10 @@ public final class AudioWaveForm { attachmentDatabase.writeAudioHash(dbAttachment.getAttachmentId(), fileInfo.toDatabaseProtobuf()); WAVE_FORM_CACHE.put(cacheKey, fileInfo); - Util.runOnMain(() -> onSuccess.accept(fileInfo)); + ThreadUtil.runOnMain(() -> onSuccess.accept(fileInfo)); } catch (Throwable e) { Log.w(TAG, "Failed to create audio wave form for " + cacheKey, e); - Util.runOnMain(onFailure); + ThreadUtil.runOnMain(onFailure); } }); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ExpirationTimerView.java b/app/src/main/java/org/thoughtcrime/securesms/components/ExpirationTimerView.java index d52b89162..1439fefc7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ExpirationTimerView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ExpirationTimerView.java @@ -6,8 +6,8 @@ import android.util.AttributeSet; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.util.Util; import java.lang.ref.WeakReference; import java.util.concurrent.TimeUnit; @@ -67,7 +67,7 @@ public class ExpirationTimerView extends androidx.appcompat.widget.AppCompatImag else stopped = false; } - Util.runOnMainDelayed(new AnimationUpdateRunnable(this), calculateAnimationDelay(this.startedAt, this.expiresIn)); + ThreadUtil.runOnMainDelayed(new AnimationUpdateRunnable(this), calculateAnimationDelay(this.startedAt, this.expiresIn)); } public void stopAnimation() { @@ -116,7 +116,7 @@ public class ExpirationTimerView extends androidx.appcompat.widget.AppCompatImag } } - Util.runOnMainDelayed(this, timerView.calculateAnimationDelay(timerView.startedAt, timerView.expiresIn)); + ThreadUtil.runOnMainDelayed(this, timerView.calculateAnimationDelay(timerView.startedAt, timerView.expiresIn)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/InputPanel.java b/app/src/main/java/org/thoughtcrime/securesms/components/InputPanel.java index b937a98be..0c1d0d468 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/InputPanel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/InputPanel.java @@ -22,10 +22,10 @@ import androidx.annotation.DimenRes; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.animation.AnimationCompleteListener; @@ -42,7 +42,6 @@ import org.thoughtcrime.securesms.mms.QuoteModel; import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; @@ -501,7 +500,7 @@ public class InputPanel extends LinearLayout this.startTime = System.currentTimeMillis(); this.recordTimeView.setText(DateUtils.formatElapsedTime(0)); ViewUtil.fadeIn(this.recordTimeView, FADE_TIME); - Util.runOnMainDelayed(this, TimeUnit.SECONDS.toMillis(1)); + ThreadUtil.runOnMainDelayed(this, TimeUnit.SECONDS.toMillis(1)); microphone.setVisibility(View.VISIBLE); microphone.startAnimation(pulseAnimation()); } @@ -527,7 +526,7 @@ public class InputPanel extends LinearLayout onLimitHit.run(); } else { recordTimeView.setText(DateUtils.formatElapsedTime(elapsedSeconds)); - Util.runOnMainDelayed(this, TimeUnit.SECONDS.toMillis(1)); + ThreadUtil.runOnMainDelayed(this, TimeUnit.SECONDS.toMillis(1)); } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/TypingStatusRepository.java b/app/src/main/java/org/thoughtcrime/securesms/components/TypingStatusRepository.java index 433456eb7..4fa1b5e17 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/TypingStatusRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/TypingStatusRepository.java @@ -10,6 +10,7 @@ import androidx.lifecycle.MutableLiveData; import com.annimon.stream.Collectors; import com.annimon.stream.Stream; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.Util; @@ -58,11 +59,11 @@ public class TypingStatusRepository { Runnable timer = timers.get(typist); if (timer != null) { - Util.cancelRunnableOnMain(timer); + ThreadUtil.cancelRunnableOnMain(timer); } timer = () -> onTypingStopped(context, threadId, author, device, false); - Util.runOnMainDelayed(timer, RECIPIENT_TYPING_TIMEOUT); + ThreadUtil.runOnMainDelayed(timer, RECIPIENT_TYPING_TIMEOUT); timers.put(typist, timer); } @@ -85,7 +86,7 @@ public class TypingStatusRepository { Runnable timer = timers.get(typist); if (timer != null) { - Util.cancelRunnableOnMain(timer); + ThreadUtil.cancelRunnableOnMain(timer); timers.remove(typist); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/TypingStatusSender.java b/app/src/main/java/org/thoughtcrime/securesms/components/TypingStatusSender.java index 5dab5b8ec..25abdca93 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/TypingStatusSender.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/TypingStatusSender.java @@ -1,11 +1,8 @@ package org.thoughtcrime.securesms.components; import android.annotation.SuppressLint; -import android.app.Application; -import android.content.Context; - -import androidx.annotation.NonNull; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobs.TypingSendJob; import org.thoughtcrime.securesms.util.Util; @@ -36,16 +33,16 @@ public class TypingStatusSender { sendTyping(threadId, true); Runnable start = new StartRunnable(threadId); - Util.runOnMainDelayed(start, REFRESH_TYPING_TIMEOUT); + ThreadUtil.runOnMainDelayed(start, REFRESH_TYPING_TIMEOUT); pair.setStart(start); } if (pair.getStop() != null) { - Util.cancelRunnableOnMain(pair.getStop()); + ThreadUtil.cancelRunnableOnMain(pair.getStop()); } Runnable stop = () -> onTypingStopped(threadId, true); - Util.runOnMainDelayed(stop, PAUSE_TYPING_TIMEOUT); + ThreadUtil.runOnMainDelayed(stop, PAUSE_TYPING_TIMEOUT); pair.setStop(stop); } @@ -62,7 +59,7 @@ public class TypingStatusSender { selfTypingTimers.put(threadId, pair); if (pair.getStart() != null) { - Util.cancelRunnableOnMain(pair.getStart()); + ThreadUtil.cancelRunnableOnMain(pair.getStart()); if (notify) { sendTyping(threadId, false); @@ -70,7 +67,7 @@ public class TypingStatusSender { } if (pair.getStop() != null) { - Util.cancelRunnableOnMain(pair.getStop()); + ThreadUtil.cancelRunnableOnMain(pair.getStop()); } pair.setStart(null); @@ -92,7 +89,7 @@ public class TypingStatusSender { @Override public void run() { sendTyping(threadId, true); - Util.runOnMainDelayed(this, REFRESH_TYPING_TIMEOUT); + ThreadUtil.runOnMainDelayed(this, REFRESH_TYPING_TIMEOUT); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/camera/CameraView.java b/app/src/main/java/org/thoughtcrime/securesms/components/camera/CameraView.java index 3c5b17290..2c1960373 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/camera/CameraView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/camera/CameraView.java @@ -36,6 +36,7 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.util.BitmapUtil; @@ -320,7 +321,7 @@ public class CameraView extends ViewGroup { camera.startPreview(); Log.i(TAG, "camera.startPreview() -> " + (System.currentTimeMillis() - previewStartMillis) + "ms"); state = State.ACTIVE; - Util.runOnMain(new Runnable() { + ThreadUtil.runOnMain(new Runnable() { @Override public void run() { requestLayout(); @@ -495,9 +496,9 @@ public class CameraView extends ViewGroup { return; } - Util.runOnMainSync(this::onPreMain); + ThreadUtil.runOnMainSync(this::onPreMain); final Result result = onRunBackground(); - Util.runOnMainSync(() -> onPostMain(result)); + ThreadUtil.runOnMainSync(() -> onPostMain(result)); } protected boolean onWait() { return true; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java index 72939dffd..7befdcaa5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java @@ -18,6 +18,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.components.emoji.parsing.EmojiDrawInfo; @@ -25,7 +26,6 @@ import org.thoughtcrime.securesms.components.emoji.parsing.EmojiPageBitmap; import org.thoughtcrime.securesms.components.emoji.parsing.EmojiParser; import org.thoughtcrime.securesms.components.emoji.parsing.EmojiTree; import org.thoughtcrime.securesms.util.FutureTaskListener; -import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.Pair; import java.util.List; @@ -118,7 +118,7 @@ class EmojiProvider { final EmojiDrawable drawable = new EmojiDrawable(drawInfo, decodeScale); drawInfo.getPage().get().addListener(new FutureTaskListener() { @Override public void onSuccess(final Bitmap result) { - Util.runOnMain(() -> drawable.setBitmap(result)); + ThreadUtil.runOnMain(() -> drawable.setBitmap(result)); } @Override public void onFailure(ExecutionException error) { @@ -170,7 +170,7 @@ class EmojiProvider { @TargetApi(VERSION_CODES.HONEYCOMB_MR1) public void setBitmap(Bitmap bitmap) { - Util.assertMainThread(); + ThreadUtil.assertMainThread(); if (VERSION.SDK_INT < VERSION_CODES.HONEYCOMB_MR1 || bmp == null || !bmp.sameAs(bitmap)) { bmp = bitmap; invalidateSelf(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/parsing/EmojiPageBitmap.java b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/parsing/EmojiPageBitmap.java index 6f52cfdd4..5039914b6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/parsing/EmojiPageBitmap.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/parsing/EmojiPageBitmap.java @@ -8,6 +8,7 @@ import android.graphics.BitmapFactory; import androidx.annotation.NonNull; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.components.emoji.EmojiPageModel; import org.thoughtcrime.securesms.util.ListenableFutureTask; @@ -39,7 +40,7 @@ public class EmojiPageBitmap { @SuppressLint("StaticFieldLeak") public ListenableFutureTask get() { - Util.assertMainThread(); + ThreadUtil.assertMainThread(); if (bitmapReference != null && bitmapReference.get() != null) { return new ListenableFutureTask<>(bitmapReference.get()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantView.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantView.java index 45285f29e..993ff207d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantView.java @@ -17,6 +17,7 @@ import androidx.core.widget.ImageViewCompat; import com.bumptech.glide.load.engine.DiskCacheStrategy; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.components.AvatarImageView; import org.thoughtcrime.securesms.components.emoji.EmojiTextView; @@ -29,7 +30,6 @@ import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.util.AvatarUtil; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import org.webrtc.RendererCommon; @@ -154,7 +154,7 @@ public class CallParticipantView extends ConstraintLayout { private boolean isMissingMediaKeys(@NonNull CallParticipant participant) { if (missingMediaKeysUpdater != null) { - Util.cancelRunnableOnMain(missingMediaKeysUpdater); + ThreadUtil.cancelRunnableOnMain(missingMediaKeysUpdater); missingMediaKeysUpdater = null; } @@ -168,7 +168,7 @@ public class CallParticipantView extends ConstraintLayout { setCallParticipant(participant); } }; - Util.runOnMainDelayed(missingMediaKeysUpdater, DELAY_SHOWING_MISSING_MEDIA_KEYS - time); + ThreadUtil.runOnMainDelayed(missingMediaKeysUpdater, DELAY_SHOWING_MISSING_MEDIA_KEYS - time); } } return false; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 2121943f6..4ee7052f6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -88,6 +88,7 @@ import com.google.android.material.button.MaterialButton; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.BlockUnblockDialog; @@ -200,7 +201,6 @@ import org.thoughtcrime.securesms.messagerequests.MessageRequestState; import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel; import org.thoughtcrime.securesms.messagerequests.MessageRequestsBottomView; import org.thoughtcrime.securesms.mms.AttachmentManager; -import org.thoughtcrime.securesms.mms.SlideFactory.MediaType; import org.thoughtcrime.securesms.mms.AudioSlide; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.GifSlide; @@ -217,6 +217,7 @@ import org.thoughtcrime.securesms.mms.QuoteModel; import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.mms.SlideFactory; +import org.thoughtcrime.securesms.mms.SlideFactory.MediaType; import org.thoughtcrime.securesms.mms.StickerSlide; import org.thoughtcrime.securesms.mms.VideoSlide; import org.thoughtcrime.securesms.notifications.NotificationChannels; @@ -455,7 +456,7 @@ public class ConversationActivity extends PassphraseRequiredActivity public void onSuccess(Boolean loadedDraft) { if (loadedDraft != null && loadedDraft) { Log.i(TAG, "Finished loading draft"); - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { if (fragment != null && fragment.isResumed()) { fragment.moveToLastSeen(); } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationAdapter.java index 9b51a52e4..19b6a6c44 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationAdapter.java @@ -36,6 +36,7 @@ import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.RecyclerView; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.signal.paging.PagingController; import org.thoughtcrime.securesms.BindableConversationItem; @@ -43,7 +44,6 @@ import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.util.CachedInflater; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.StickyHeaderDecoration; @@ -545,7 +545,7 @@ public class ConversationAdapter @MainThread private void cleanFastRecords() { - Util.assertMainThread(); + ThreadUtil.assertMainThread(); synchronized (releasedFastRecords) { Iterator messageIterator = fastRecords.iterator(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java index a72550c07..7769ddc69 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java @@ -7,11 +7,11 @@ import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.conversationlist.model.MessageResult; import org.thoughtcrime.securesms.database.CursorList; import org.thoughtcrime.securesms.search.SearchRepository; import org.thoughtcrime.securesms.util.Debouncer; -import org.thoughtcrime.securesms.util.Util; import java.util.List; @@ -101,7 +101,7 @@ public class ConversationSearchViewModel extends AndroidViewModel { firstSearch = false; searchRepository.query(query, threadId, messages -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { if (searchOpen && query.equals(activeQuery)) { result.setValue(new SearchResult(messages, 0)); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.java index 71f7628ab..ffd7489f5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.java @@ -9,6 +9,7 @@ import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.signal.paging.PagedData; import org.signal.paging.PagingConfig; @@ -25,7 +26,6 @@ import org.thoughtcrime.securesms.net.PipeConnectivityListener; import org.thoughtcrime.securesms.search.SearchRepository; import org.thoughtcrime.securesms.util.Debouncer; import org.thoughtcrime.securesms.util.ThrottledDebouncer; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.thoughtcrime.securesms.util.paging.Invalidator; @@ -141,7 +141,7 @@ class ConversationListViewModel extends ViewModel { void updateQuery(String query) { lastQuery = query; searchDebouncer.publish(() -> searchRepository.query(query, result -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { if (query.equals(lastQuery)) { searchResult.setValue(result); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java index eabd82fd9..8d3f54793 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java @@ -7,7 +7,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; -import org.thoughtcrime.securesms.util.Util; +import org.signal.core.util.ThreadUtil; import org.whispersystems.signalservice.api.util.UuidUtil; import java.util.Collection; @@ -110,7 +110,7 @@ public final class UpdateDescription { return staticString; } - Util.assertNotMainThread(); + ThreadUtil.assertNotMainThread(); //noinspection ConstantConditions return stringFactory.create(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2ProcessingLock.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2ProcessingLock.java index af0dc24da..a8a4d7021 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2ProcessingLock.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2ProcessingLock.java @@ -2,8 +2,8 @@ package org.thoughtcrime.securesms.groups; import androidx.annotation.WorkerThread; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.util.Util; import java.io.Closeable; import java.util.concurrent.TimeUnit; @@ -26,7 +26,7 @@ final class GroupsV2ProcessingLock { @WorkerThread static Closeable acquireGroupProcessingLock(long timeoutMs) throws GroupChangeBusyException { - Util.assertNotMainThread(); + ThreadUtil.assertNotMainThread(); try { if (!lock.tryLock(timeoutMs, TimeUnit.MILLISECONDS)) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/managegroup/ManageGroupViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/managegroup/ManageGroupViewModel.java index 665ea8526..1d8bebbd0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/managegroup/ManageGroupViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/managegroup/ManageGroupViewModel.java @@ -16,6 +16,7 @@ import androidx.lifecycle.Transformations; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.BlockUnblockDialog; import org.thoughtcrime.securesms.ContactSelectionListFragment; import org.thoughtcrime.securesms.ExpirationDialog; @@ -44,7 +45,6 @@ import org.thoughtcrime.securesms.util.AsynchronousCallback; import org.thoughtcrime.securesms.util.DefaultValueLiveData; import org.thoughtcrime.securesms.util.ExpirationUtil; import org.thoughtcrime.securesms.util.FeatureFlags; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.thoughtcrime.securesms.util.views.SimpleProgressDialog; @@ -320,7 +320,7 @@ public class ManageGroupViewModel extends ViewModel { @WorkerThread private void showErrorToast(@NonNull GroupChangeFailureReason e) { - Util.runOnMain(() -> Toast.makeText(context, GroupErrors.getUserDisplayMessage(e), Toast.LENGTH_LONG).show()); + ThreadUtil.runOnMain(() -> Toast.makeText(context, GroupErrors.getUserDisplayMessage(e), Toast.LENGTH_LONG).show()); } public void onAddMembersClick(@NonNull Fragment fragment, int resultCode) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java index 000d85f13..7e0ca6373 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java @@ -9,8 +9,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory; import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer; import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage; @@ -58,7 +58,7 @@ public class JobManager implements ConstraintObserver.Notifier { public JobManager(@NonNull Application application, @NonNull Configuration configuration) { this.application = application; this.configuration = configuration; - this.executor = new FilteredExecutor(configuration.getExecutorFactory().newSingleThreadExecutor("signal-JobManager"), Util::isMainThread); + this.executor = new FilteredExecutor(configuration.getExecutorFactory().newSingleThreadExecutor("signal-JobManager"), ThreadUtil::isMainThread); this.jobTracker = configuration.getJobTracker(); this.jobController = new JobController(application, configuration.getJobStorage(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewViewModel.java index d81fea67a..8fe9560e9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewViewModel.java @@ -11,10 +11,10 @@ import androidx.lifecycle.Transformations; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.net.RequestController; import org.thoughtcrime.securesms.util.Debouncer; -import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.guava.Optional; import java.util.Collections; @@ -99,7 +99,7 @@ public class LinkPreviewViewModel extends ViewModel { activeRequest = repository.getLinkPreview(context, link.get().getUrl(), new LinkPreviewRepository.Callback() { @Override public void onSuccess(@NonNull LinkPreview linkPreview) { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { if (!userCanceled) { if (activeUrl != null && activeUrl.equals(linkPreview.getUrl())) { linkPreviewState.setValue(LinkPreviewState.forPreview(linkPreview)); @@ -113,7 +113,7 @@ public class LinkPreviewViewModel extends ViewModel { @Override public void onError(@NonNull LinkPreviewRepository.Error error) { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { if (!userCanceled) { linkPreviewState.setValue(LinkPreviewState.forLinksWithNoPreview(error)); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionViewModel.java index d181618cb..ff4a6ca28 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionViewModel.java @@ -7,9 +7,9 @@ import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.SingleLiveEvent; -import org.thoughtcrime.securesms.util.Util; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -34,7 +34,7 @@ class CameraContactSelectionViewModel extends ViewModel { this.selected = new LinkedHashSet<>(); repository.getCameraContacts(cameraContacts -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { contacts.postValue(new ContactState(cameraContacts, new ArrayList<>(selected), currentQuery)); }); }); @@ -56,7 +56,7 @@ class CameraContactSelectionViewModel extends ViewModel { this.currentQuery = query; repository.getCameraContacts(query, cameraContacts -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { contacts.postValue(new ContactState(cameraContacts, new ArrayList<>(selected), query)); }); }); @@ -64,7 +64,7 @@ class CameraContactSelectionViewModel extends ViewModel { void onRefresh() { repository.getCameraContacts(cameraContacts -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { contacts.postValue(new ContactState(cameraContacts, new ArrayList<>(selected), currentQuery)); }); }); diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java index 776f92b3a..6abc0ee15 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java @@ -15,6 +15,7 @@ import androidx.lifecycle.ViewModelProvider; import com.annimon.stream.Stream; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.TransportOption; import org.thoughtcrime.securesms.database.ThreadDatabase; @@ -144,7 +145,7 @@ class MediaSendViewModel extends ViewModel { } repository.getPopulatedMedia(context, newMedia, populatedMedia -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { List filteredMedia = getFilteredMedia(context, populatedMedia, mediaConstraints); if (filteredMedia.size() != newMedia.size()) { @@ -196,7 +197,7 @@ class MediaSendViewModel extends ViewModel { selectedMedia.setValue(Collections.singletonList(media)); repository.getPopulatedMedia(context, Collections.singletonList(media), populatedMedia -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { List filteredMedia = getFilteredMedia(context, populatedMedia, mediaConstraints); if (filteredMedia.isEmpty()) { @@ -654,7 +655,7 @@ class MediaSendViewModel extends ViewModel { // XXX We must do this to avoid sending out messages to the same recipient with the same // sentTimestamp. If we do this, they'll be considered dupes by the receiver. - Util.sleep(5); + ThreadUtil.sleep(5); } MessageSender.sendMediaBroadcast(application, messages, preUploadResults); diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/ClientDeprecatedActivity.java b/app/src/main/java/org/thoughtcrime/securesms/megaphone/ClientDeprecatedActivity.java index 7ab4bd66d..c6b57088e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/ClientDeprecatedActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/ClientDeprecatedActivity.java @@ -4,13 +4,13 @@ import android.os.Bundle; import androidx.appcompat.app.AlertDialog; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.PassphraseRequiredActivity; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.PlayStoreUtil; -import org.thoughtcrime.securesms.util.Util; /** * Shown when a users build fully expires. Controlled by {@link Megaphones.Event#CLIENT_DEPRECATED}. @@ -53,7 +53,7 @@ public class ClientDeprecatedActivity extends PassphraseRequiredActivity { .setMessage(R.string.ClientDeprecatedActivity_your_version_of_signal_has_expired_you_can_view_your_message_history) .setPositiveButton(R.string.ClientDeprecatedActivity_dont_update, (dialog, which) -> { ApplicationDependencies.getMegaphoneRepository().markFinished(Megaphones.Event.CLIENT_DEPRECATED, () -> { - Util.runOnMain(this::finish); + ThreadUtil.runOnMain(this::finish); }); }) .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageHeaderViewHolder.java b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageHeaderViewHolder.java index 4f63908f6..2ddcd363b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageHeaderViewHolder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageHeaderViewHolder.java @@ -12,6 +12,7 @@ import androidx.annotation.Nullable; import androidx.lifecycle.LifecycleOwner; import androidx.recyclerview.widget.RecyclerView; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.conversation.ConversationItem; @@ -21,7 +22,6 @@ import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.ExpirationUtil; -import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.guava.Optional; import java.sql.Date; @@ -156,7 +156,7 @@ final class MessageHeaderViewHolder extends RecyclerView.ViewHolder { expiresGroup.setVisibility(View.VISIBLE); if (running) { expiresUpdater = new ExpiresUpdater(messageRecord); - Util.runOnMain(expiresUpdater); + ThreadUtil.runOnMain(expiresUpdater); } } @@ -203,7 +203,7 @@ final class MessageHeaderViewHolder extends RecyclerView.ViewHolder { expiresIn.setText(duration); if (running && expirationTime > 1) { - Util.runOnMainDelayed(this, 500); + ThreadUtil.runOnMainDelayed(this, 500); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java b/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java index c8385b06e..8c2278a26 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java @@ -38,6 +38,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.MediaPreviewActivity; import org.thoughtcrime.securesms.R; @@ -58,7 +59,6 @@ import org.thoughtcrime.securesms.providers.DeprecatedPersistentBlobProvider; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.MediaUtil; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; @@ -207,7 +207,7 @@ public class AttachmentManager { .createForSingleSessionInMemory(); LocationSlide locationSlide = new LocationSlide(context, uri, blob.length, place); - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { setSlide(locationSlide); attachmentListener.onAttachmentChanged(); returnResult.set(true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditViewModel.java index c6873cec3..13ff7099d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditViewModel.java @@ -9,13 +9,13 @@ import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.SingleLiveEvent; import org.thoughtcrime.securesms.util.UsernameUtil; import org.thoughtcrime.securesms.util.UsernameUtil.InvalidReason; -import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.guava.Optional; class UsernameEditViewModel extends ViewModel { @@ -73,7 +73,7 @@ class UsernameEditViewModel extends ViewModel { uiState.setValue(new State(ButtonState.SUBMIT_LOADING, UsernameStatus.NONE)); repo.setUsername(username, (result) -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { switch (result) { case SUCCESS: uiState.setValue(new State(ButtonState.SUBMIT_DISABLED, UsernameStatus.NONE)); @@ -100,7 +100,7 @@ class UsernameEditViewModel extends ViewModel { uiState.setValue(new State(ButtonState.DELETE_LOADING, UsernameStatus.NONE)); repo.deleteUsername((result) -> { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { switch (result) { case SUCCESS: uiState.postValue(new State(ButtonState.DELETE_DISABLED, UsernameStatus.NONE)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiRepository.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiRepository.java index 5d9b0e4db..e32aaffd7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiRepository.java @@ -8,6 +8,7 @@ import androidx.annotation.StringRes; import com.annimon.stream.Stream; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; @@ -21,7 +22,6 @@ import org.thoughtcrime.securesms.database.model.ReactionRecord; import org.thoughtcrime.securesms.reactions.ReactionDetails; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.sms.MessageSender; -import org.thoughtcrime.securesms.util.Util; import java.util.Arrays; import java.util.Collections; @@ -80,7 +80,7 @@ final class ReactWithAnyEmojiRepository { MessageSender.sendReactionRemoval(context, messageRecord.getId(), messageRecord.isMms(), oldRecord); } else { MessageSender.sendNewReaction(context, messageRecord.getId(), messageRecord.isMms(), emoji); - Util.runOnMain(() -> recentEmojiPageModel.onCodePointSelected(emoji)); + ThreadUtil.runOnMain(() -> recentEmojiPageModel.onCodePointSelected(emoji)); } } catch (NoSuchMessageException e) { Log.w(TAG, "Message not found! Ignoring."); diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipient.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipient.java index e015377d1..0dd6a2b09 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipient.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipient.java @@ -11,13 +11,13 @@ import androidx.lifecycle.Observer; import com.annimon.stream.Stream; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.whispersystems.libsignal.util.guava.Optional; @@ -79,14 +79,14 @@ public final class LiveRecipient { * use {@link #removeObservers(LifecycleOwner)}. */ public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) { - Util.postToMain(() -> observableLiveData.observe(owner, observer)); + ThreadUtil.postToMain(() -> observableLiveData.observe(owner, observer)); } /** * Removes all observers of this data registered for the given LifecycleOwner. */ public void removeObservers(@NonNull LifecycleOwner owner) { - Util.runOnMain(() -> observableLiveData.removeObservers(owner)); + ThreadUtil.runOnMain(() -> observableLiveData.removeObservers(owner)); } /** @@ -95,7 +95,7 @@ public final class LiveRecipient { * {@link #observe(LifecycleOwner, Observer)} if possible, as it is lifecycle-safe. */ public void observeForever(@NonNull RecipientForeverObserver observer) { - Util.postToMain(() -> { + ThreadUtil.postToMain(() -> { if (observers.isEmpty()) { observableLiveData.observeForever(foreverObserver); } @@ -107,7 +107,7 @@ public final class LiveRecipient { * Unsubscribes the provided {@link RecipientForeverObserver} from future changes. */ public void removeForeverObserver(@NonNull RecipientForeverObserver observer) { - Util.postToMain(() -> { + ThreadUtil.postToMain(() -> { observers.remove(observer); if (observers.isEmpty()) { @@ -127,7 +127,7 @@ public final class LiveRecipient { return current; } - if (Util.isMainThread()) { + if (ThreadUtil.isMainThread()) { Log.w(TAG, "[Resolve][MAIN] " + getId(), new Throwable()); } @@ -163,7 +163,7 @@ public final class LiveRecipient { if (getId().isUnknown()) return; - if (Util.isMainThread()) { + if (ThreadUtil.isMainThread()) { Log.w(TAG, "[Refresh][MAIN] " + id, new Throwable()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/ui/bottomsheet/RecipientDialogViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/ui/bottomsheet/RecipientDialogViewModel.java index ba3c44ae1..ccc30154b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/ui/bottomsheet/RecipientDialogViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/ui/bottomsheet/RecipientDialogViewModel.java @@ -15,6 +15,7 @@ import androidx.lifecycle.Transformations; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.BlockUnblockDialog; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.VerifyIdentityActivity; @@ -30,7 +31,6 @@ import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.recipients.ui.managerecipient.ManageRecipientActivity; import org.thoughtcrime.securesms.util.CommunicationActions; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import java.util.Objects; @@ -205,7 +205,7 @@ final class RecipientDialogViewModel extends ViewModel { @WorkerThread private void showErrorToast(@NonNull GroupChangeFailureReason e) { - Util.runOnMain(() -> Toast.makeText(context, GroupErrors.getUserDisplayMessage(e), Toast.LENGTH_LONG).show()); + ThreadUtil.runOnMain(() -> Toast.makeText(context, GroupErrors.getUserDisplayMessage(e), Toast.LENGTH_LONG).show()); } static class AdminActionStatus { diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/ui/managerecipient/ManageRecipientViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/ui/managerecipient/ManageRecipientViewModel.java index dcea1518a..73d105fee 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/ui/managerecipient/ManageRecipientViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/ui/managerecipient/ManageRecipientViewModel.java @@ -16,6 +16,7 @@ import androidx.lifecycle.ViewModelProvider; import com.annimon.stream.Stream; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.BlockUnblockDialog; import org.thoughtcrime.securesms.ExpirationDialog; import org.thoughtcrime.securesms.R; @@ -38,7 +39,6 @@ import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.DefaultValueLiveData; import org.thoughtcrime.securesms.util.ExpirationUtil; import org.thoughtcrime.securesms.util.Hex; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import java.util.List; @@ -207,11 +207,11 @@ public final class ManageRecipientViewModel extends ViewModel { } void onAddToGroupButton(@NonNull Activity activity) { - manageRecipientRepository.getGroupMembership(existingGroups -> Util.runOnMain(() -> activity.startActivity(AddToGroupsActivity.newIntent(activity, manageRecipientRepository.getRecipientId(), existingGroups)))); + manageRecipientRepository.getGroupMembership(existingGroups -> ThreadUtil.runOnMain(() -> activity.startActivity(AddToGroupsActivity.newIntent(activity, manageRecipientRepository.getRecipientId(), existingGroups)))); } private void withRecipient(@NonNull Consumer mainThreadRecipientCallback) { - manageRecipientRepository.getRecipient(recipient -> Util.runOnMain(() -> mainThreadRecipientCallback.accept(recipient))); + manageRecipientRepository.getRecipient(recipient -> ThreadUtil.runOnMain(() -> mainThreadRecipientCallback.accept(recipient))); } private static @NonNull List filterSharedGroupList(@NonNull List groups, diff --git a/app/src/main/java/org/thoughtcrime/securesms/revealable/ViewOnceMessageViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/revealable/ViewOnceMessageViewModel.java index 4c1c93ccb..8247fe949 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/revealable/ViewOnceMessageViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/revealable/ViewOnceMessageViewModel.java @@ -10,10 +10,10 @@ import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.DatabaseContentProviders; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; -import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.guava.Optional; class ViewOnceMessageViewModel extends ViewModel { @@ -59,7 +59,7 @@ class ViewOnceMessageViewModel extends ViewModel { } private void onMessageRetrieved(@NonNull Optional optionalMessage) { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { MmsMessageRecord current = message.getValue() != null ? message.getValue().orNull() : null; MmsMessageRecord proposed = optionalMessage.orNull(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java index a7625b476..132a3e6d2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java @@ -5,6 +5,7 @@ import android.os.ResultReceiver; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.signal.ringrtc.CallException; import org.signal.ringrtc.CallId; @@ -15,7 +16,6 @@ import org.thoughtcrime.securesms.ringrtc.CallState; import org.thoughtcrime.securesms.ringrtc.IceCandidateParcel; import org.thoughtcrime.securesms.ringrtc.RemotePeer; import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.webrtc.audio.OutgoingRinger; import org.whispersystems.signalservice.api.messages.calls.IceUpdateMessage; import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage; @@ -196,7 +196,7 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor { OutgoingRinger ringer = new OutgoingRinger(context); ringer.start(OutgoingRinger.Type.BUSY); - Util.runOnMainDelayed(ringer::stop, BUSY_TONE_LENGTH); + ThreadUtil.runOnMainDelayed(ringer::stop, BUSY_TONE_LENGTH); } else if (action.equals(ACTION_ENDED_REMOTE_GLARE) && incomingBeforeAccept) { webRtcInteractor.insertMissedCall(remotePeer, true, remotePeer.getCallStartTimestamp(), currentState.getCallSetupState().isRemoteVideoOffer()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcVideoUtil.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcVideoUtil.java index 2b113e0bb..28b5f50f6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcVideoUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcVideoUtil.java @@ -4,6 +4,7 @@ import android.content.Context; import androidx.annotation.NonNull; +import org.signal.core.util.ThreadUtil; import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink; import org.thoughtcrime.securesms.components.webrtc.OrientationAwareVideoSink; import org.thoughtcrime.securesms.ringrtc.Camera; @@ -11,7 +12,6 @@ import org.thoughtcrime.securesms.ringrtc.CameraEventListener; import org.thoughtcrime.securesms.ringrtc.CameraState; import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState; import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceStateBuilder; -import org.thoughtcrime.securesms.util.Util; import org.webrtc.CapturerObserver; import org.webrtc.EglBase; import org.webrtc.VideoFrame; @@ -31,7 +31,7 @@ public final class WebRtcVideoUtil { { final WebRtcServiceStateBuilder builder = currentState.builder(); - Util.runOnMainSync(() -> { + ThreadUtil.runOnMainSync(() -> { EglBase eglBase = EglBase.create(); BroadcastVideoSink localSink = new BroadcastVideoSink(eglBase); Camera camera = new Camera(context, cameraEventListener, eglBase, CameraState.Direction.FRONT); @@ -57,7 +57,7 @@ public final class WebRtcVideoUtil { { final WebRtcServiceStateBuilder builder = currentState.builder(); - Util.runOnMainSync(() -> { + ThreadUtil.runOnMainSync(() -> { Camera camera = currentState.getVideoState().requireCamera(); camera.setEnabled(false); camera.dispose(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/shakereport/ShakeToReport.java b/app/src/main/java/org/thoughtcrime/securesms/shakereport/ShakeToReport.java index 2ef5c986a..e4b18be7a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/shakereport/ShakeToReport.java +++ b/app/src/main/java/org/thoughtcrime/securesms/shakereport/ShakeToReport.java @@ -9,16 +9,15 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import org.signal.core.util.ShakeDetector; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.signal.core.util.tracing.Tracer; -import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogRepository; import org.thoughtcrime.securesms.sharing.ShareIntents; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.ServiceUtil; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.views.SimpleProgressDialog; import java.lang.ref.WeakReference; @@ -96,7 +95,7 @@ public final class ShakeToReport implements ShakeDetector.Listener { repo.submitLog(lines, Tracer.getInstance().serialize(), url -> { Log.i(TAG, "Logs uploaded!"); - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { spinner.dismiss(); if (url.isPresent()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/AppForegroundObserver.java b/app/src/main/java/org/thoughtcrime/securesms/util/AppForegroundObserver.java index 9a9587c42..f077f8afb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/AppForegroundObserver.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/AppForegroundObserver.java @@ -7,6 +7,8 @@ import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ProcessLifecycleOwner; +import org.signal.core.util.ThreadUtil; + import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -22,7 +24,7 @@ public final class AppForegroundObserver { @MainThread public void begin() { - Util.assertMainThread(); + ThreadUtil.assertMainThread(); ProcessLifecycleOwner.get().getLifecycle().addObserver(new DefaultLifecycleObserver() { @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/AsynchronousCallback.java b/app/src/main/java/org/thoughtcrime/securesms/util/AsynchronousCallback.java index f0fdcbe4e..1a5370acd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/AsynchronousCallback.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/AsynchronousCallback.java @@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.util; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.signal.core.util.ThreadUtil; + public final class AsynchronousCallback { /** @@ -51,12 +53,12 @@ public final class AsynchronousCallback { return new WorkerThread() { @Override public void onComplete(@Nullable R result) { - Util.runOnMain(() -> MainThread.this.onComplete(result)); + ThreadUtil.runOnMain(() -> MainThread.this.onComplete(result)); } @Override public void onError(@Nullable E error) { - Util.runOnMain(() -> MainThread.this.onError(error)); + ThreadUtil.runOnMain(() -> MainThread.this.onError(error)); } }; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java index 196b9f553..6ff81f689 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java @@ -20,6 +20,7 @@ import androidx.exifinterface.media.ExifInterface; import com.bumptech.glide.load.engine.DiskCacheStrategy; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.MediaConstraints; @@ -410,7 +411,7 @@ public class BitmapUtil { } }; - Util.runOnMain(runnable); + ThreadUtil.runOnMain(runnable); synchronized (result) { while (!created.get()) Util.wait(result, 0); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/CachedInflater.java b/app/src/main/java/org/thoughtcrime/securesms/util/CachedInflater.java index 733267558..0bc52bab5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/CachedInflater.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/CachedInflater.java @@ -12,6 +12,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.asynclayoutinflater.view.AsyncLayoutInflater; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.util.concurrent.SerialExecutor; @@ -124,7 +125,7 @@ public class CachedInflater { } AsyncLayoutInflater.OnInflateFinishedListener onInflateFinishedListener = (view, resId, p) -> { - Util.assertMainThread(); + ThreadUtil.assertMainThread(); if (enqueueTime < lastClearTime) { Log.d(TAG, "Prefetch is no longer valid. Ignoring."); return; diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SignalProxyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/SignalProxyUtil.java index 8cdb6affd..4ab213303 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SignalProxyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SignalProxyUtil.java @@ -6,6 +6,7 @@ import androidx.annotation.WorkerThread; import androidx.lifecycle.Observer; import org.conscrypt.Conscrypt; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; @@ -16,10 +17,6 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.internal.configuration.SignalProxy; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -97,14 +94,14 @@ public final class SignalProxyUtil { } }; - Util.runOnMainSync(() -> ApplicationDependencies.getPipeListener().getState().observeForever(observer)); + ThreadUtil.runOnMainSync(() -> ApplicationDependencies.getPipeListener().getState().observeForever(observer)); try { latch.await(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { Log.w(TAG, "Interrupted!", e); } finally { - Util.runOnMainSync(() -> ApplicationDependencies.getPipeListener().getState().removeObserver(observer)); + ThreadUtil.runOnMainSync(() -> ApplicationDependencies.getPipeListener().getState().removeObserver(observer)); } return success.get(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/Util.java b/app/src/main/java/org/thoughtcrime/securesms/util/Util.java index eb3a82bab..c1eb02af6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/Util.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/Util.java @@ -27,8 +27,6 @@ import android.graphics.Typeface; import android.net.Uri; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; -import android.os.Handler; -import android.os.Looper; import android.provider.Telephony; import android.telephony.TelephonyManager; import android.text.Spannable; @@ -47,7 +45,6 @@ import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; -import org.signal.core.util.LinkedBlockingLifoQueue; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.BuildConfig; import org.thoughtcrime.securesms.components.ComposeText; @@ -66,9 +63,6 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class Util { @@ -76,8 +70,6 @@ public class Util { private static final long BUILD_LIFESPAN = TimeUnit.DAYS.toMillis(90); - private static volatile Handler handler; - public static List asList(T... elements) { List result = new LinkedList<>(); Collections.addAll(result, elements); @@ -148,17 +140,6 @@ public class Util { return out.toString(); } - public static ExecutorService newSingleThreadedLifoExecutor() { - ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingLifoQueue()); - - executor.execute(() -> { -// Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - Thread.currentThread().setPriority(Thread.MIN_PRIORITY); - }); - - return executor; - } - public static boolean isEmpty(EncodedStringValue[] value) { return value == null || value.length == 0; } @@ -422,59 +403,6 @@ public class Util { return (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) || OutgoingLegacyMmsConnection.isConnectionPossible(context); } - public static boolean isMainThread() { - return Looper.myLooper() == Looper.getMainLooper(); - } - - public static void assertMainThread() { - if (!isMainThread()) { - throw new AssertionError("Must run on main thread."); - } - } - - public static void assertNotMainThread() { - if (isMainThread()) { - throw new AssertionError("Cannot run on main thread."); - } - } - - public static void postToMain(final @NonNull Runnable runnable) { - getHandler().post(runnable); - } - - public static void runOnMain(final @NonNull Runnable runnable) { - if (isMainThread()) runnable.run(); - else getHandler().post(runnable); - } - - public static void runOnMainDelayed(final @NonNull Runnable runnable, long delayMillis) { - getHandler().postDelayed(runnable, delayMillis); - } - - public static void cancelRunnableOnMain(@NonNull Runnable runnable) { - getHandler().removeCallbacks(runnable); - } - - public static void runOnMainSync(final @NonNull Runnable runnable) { - if (isMainThread()) { - runnable.run(); - } else { - final CountDownLatch sync = new CountDownLatch(1); - runOnMain(() -> { - try { - runnable.run(); - } finally { - sync.countDown(); - } - }); - try { - sync.await(); - } catch (InterruptedException ie) { - throw new AssertionError(ie); - } - } - } - public static T getRandomElement(T[] elements) { return elements[new SecureRandom().nextInt(elements.length)]; } @@ -551,29 +479,10 @@ public class Util { return MemoryUnitFormat.formatBytes(sizeBytes); } - public static void sleep(long millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - throw new AssertionError(e); - } - } - public static void copyToClipboard(@NonNull Context context, @NonNull String text) { ServiceUtil.getClipboardManager(context).setPrimaryClip(ClipData.newPlainText("text", text)); } - private static Handler getHandler() { - if (handler == null) { - synchronized (Util.class) { - if (handler == null) { - handler = new Handler(Looper.getMainLooper()); - } - } - } - return handler; - } - @SafeVarargs public static List concatenatedList(Collection ... items) { final List concat = new ArrayList<>(Stream.of(items).reduce(0, (sum, list) -> sum + list.size())); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/concurrent/SimpleTask.java b/app/src/main/java/org/thoughtcrime/securesms/util/concurrent/SimpleTask.java index 43d12ecd4..0ddb5540c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/concurrent/SimpleTask.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/concurrent/SimpleTask.java @@ -5,8 +5,8 @@ import android.os.AsyncTask; import androidx.annotation.NonNull; import androidx.lifecycle.Lifecycle; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; -import org.thoughtcrime.securesms.util.Util; import java.util.concurrent.Executor; @@ -28,7 +28,7 @@ public class SimpleTask { final E result = backgroundTask.run(); if (isValid(lifecycle)) { - Util.runOnMain(() -> { + ThreadUtil.runOnMain(() -> { if (isValid(lifecycle)) { foregroundTask.run(result); } @@ -52,7 +52,7 @@ public class SimpleTask { public static void run(@NonNull Executor executor, @NonNull BackgroundTask backgroundTask, @NonNull ForegroundTask foregroundTask) { executor.execute(() -> { final E result = backgroundTask.run(); - Util.runOnMain(() -> foregroundTask.run(result)); + ThreadUtil.runOnMain(() -> foregroundTask.run(result)); }); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/views/SimpleProgressDialog.java b/app/src/main/java/org/thoughtcrime/securesms/util/views/SimpleProgressDialog.java index 5a99bc3d1..5ff2a3e7c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/views/SimpleProgressDialog.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/views/SimpleProgressDialog.java @@ -7,9 +7,9 @@ import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; +import org.signal.core.util.ThreadUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.util.Util; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -66,18 +66,18 @@ public final class SimpleProgressDialog { dialogAtomicReference.set(show(context)); }; - Util.runOnMainDelayed(showRunnable, delayMs); + ThreadUtil.runOnMainDelayed(showRunnable, delayMs); return () -> { - Util.cancelRunnableOnMain(showRunnable); - Util.runOnMain(() -> { + 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) { - Util.runOnMainDelayed(alertDialog::dismiss, remainingTimeMs); + ThreadUtil.runOnMainDelayed(alertDialog::dismiss, remainingTimeMs); } else { alertDialog.dismiss(); } diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java b/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java index 1dd53f438..71df99ca1 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java @@ -18,6 +18,7 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.rule.PowerMockRule; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; +import org.signal.core.util.ThreadUtil; import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; @@ -47,7 +48,7 @@ import static org.thoughtcrime.securesms.util.StringUtil.isolateBidi; @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE, application = Application.class) @PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*", "androidx.*" }) -@PrepareForTest(Util.class) +@PrepareForTest(ThreadUtil.class) public final class GroupsV2UpdateMessageProducerTest { private UUID you; diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/model/UpdateDescriptionTest.java b/app/src/test/java/org/thoughtcrime/securesms/database/model/UpdateDescriptionTest.java index 0595f7dc1..ce0e6ce9a 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/model/UpdateDescriptionTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/database/model/UpdateDescriptionTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import org.thoughtcrime.securesms.util.Util; +import org.signal.core.util.ThreadUtil; import java.util.Arrays; import java.util.Collections; @@ -19,7 +19,7 @@ import static org.junit.Assert.assertTrue; import static org.thoughtcrime.securesms.testutil.MainThreadUtil.setMainThread; @RunWith(PowerMockRunner.class) -@PrepareForTest(Util.class) +@PrepareForTest(ThreadUtil.class) public final class UpdateDescriptionTest { @Before diff --git a/app/src/test/java/org/thoughtcrime/securesms/testutil/MainThreadUtil.java b/app/src/test/java/org/thoughtcrime/securesms/testutil/MainThreadUtil.java index a83dd0682..d2addeddf 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/testutil/MainThreadUtil.java +++ b/app/src/test/java/org/thoughtcrime/securesms/testutil/MainThreadUtil.java @@ -1,6 +1,6 @@ package org.thoughtcrime.securesms.testutil; -import org.thoughtcrime.securesms.util.Util; +import org.signal.core.util.ThreadUtil; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.doCallRealMethod; @@ -12,17 +12,17 @@ public final class MainThreadUtil { } /** - * Makes {@link Util}'s Main thread assertions pass or fail during tests. + * Makes {@link ThreadUtil}'s Main thread assertions pass or fail during tests. *

* Use with {@link org.powermock.modules.junit4.PowerMockRunner} or robolectric with powermock * rule and {@code @PrepareForTest(Util.class)} */ public static void setMainThread(boolean isMainThread) { - mockStatic(Util.class); - when(Util.isMainThread()).thenReturn(isMainThread); + mockStatic(ThreadUtil.class); + when(ThreadUtil.isMainThread()).thenReturn(isMainThread); try { - doCallRealMethod().when(Util.class, "assertMainThread"); - doCallRealMethod().when(Util.class, "assertNotMainThread"); + doCallRealMethod().when(ThreadUtil.class, "assertMainThread"); + doCallRealMethod().when(ThreadUtil.class, "assertNotMainThread"); } catch (Exception e) { throw new AssertionError(); } diff --git a/core-util/src/main/java/org/signal/core/util/ThreadUtil.java b/core-util/src/main/java/org/signal/core/util/ThreadUtil.java new file mode 100644 index 000000000..54d68ba43 --- /dev/null +++ b/core-util/src/main/java/org/signal/core/util/ThreadUtil.java @@ -0,0 +1,90 @@ +package org.signal.core.util; + +import android.os.Handler; +import android.os.Looper; + +import androidx.annotation.NonNull; + +import java.util.concurrent.CountDownLatch; + +/** + * Thread related utility functions. + */ +public final class ThreadUtil { + + private static volatile Handler handler; + + private ThreadUtil() {} + + private static Handler getHandler() { + if (handler == null) { + synchronized (ThreadUtil.class) { + if (handler == null) { + handler = new Handler(Looper.getMainLooper()); + } + } + } + return handler; + } + + public static boolean isMainThread() { + return Looper.myLooper() == Looper.getMainLooper(); + } + + public static void assertMainThread() { + if (!isMainThread()) { + throw new AssertionError("Must run on main thread."); + } + } + + public static void assertNotMainThread() { + if (isMainThread()) { + throw new AssertionError("Cannot run on main thread."); + } + } + + public static void postToMain(final @NonNull Runnable runnable) { + getHandler().post(runnable); + } + + public static void runOnMain(final @NonNull Runnable runnable) { + if (isMainThread()) runnable.run(); + else getHandler().post(runnable); + } + + public static void runOnMainDelayed(final @NonNull Runnable runnable, long delayMillis) { + getHandler().postDelayed(runnable, delayMillis); + } + + public static void cancelRunnableOnMain(@NonNull Runnable runnable) { + getHandler().removeCallbacks(runnable); + } + + public static void runOnMainSync(final @NonNull Runnable runnable) { + if (isMainThread()) { + runnable.run(); + } else { + final CountDownLatch sync = new CountDownLatch(1); + runOnMain(() -> { + try { + runnable.run(); + } finally { + sync.countDown(); + } + }); + try { + sync.await(); + } catch (InterruptedException ie) { + throw new AssertionError(ie); + } + } + } + + public static void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + throw new AssertionError(e); + } + } +}