Improve organization of glide packages.

Generic image processing classes were scattered alongside Signal-specific Glide code across multiple packages: `org.signal.glide`, `org.thoughtcrime.securesms.glide` and `org.thoughtcrime.securesms.mms`.

This change provides a clearer separation of concerns:
- `org.signal.glide` contains generic image loading components
- `org.thoughtcrime.securesms.glide` contains Signal-specific Glide integrations
- Feature-specific loaders are moved to their respective domain packages (e.g. `.badges`, `.contacts`)
This commit is contained in:
jeffrey-signal
2025-08-15 12:44:42 -04:00
committed by Jeffrey Starke
parent cc43add7af
commit 47508495ed
48 changed files with 220 additions and 179 deletions

View File

@@ -1,4 +1,9 @@
package org.thoughtcrime.securesms.mms;
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.glide.common.io;
import android.content.ContentResolver;
import android.content.Context;
@@ -10,6 +15,7 @@ import com.bumptech.glide.load.data.StreamLocalUriFetcher;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.util.BitmapDecodingException;
import org.thoughtcrime.securesms.util.BitmapUtil;

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.glide
package org.signal.glide.common.io
import android.app.ActivityManager
import android.content.Context
@@ -11,9 +11,9 @@ import org.signal.core.util.ByteSize
import org.signal.core.util.bytes
import org.signal.core.util.gibiBytes
import org.signal.core.util.mebiBytes
import org.signal.glide.common.io.GlideStreamConfig.MAX_MARK_LIMIT
import org.signal.glide.common.io.GlideStreamConfig.MIN_MARK_LIMIT
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.glide.GlideStreamConfig.MAX_MARK_LIMIT
import org.thoughtcrime.securesms.glide.GlideStreamConfig.MIN_MARK_LIMIT
object GlideStreamConfig {
private val MIN_MARK_LIMIT: ByteSize = 5.mebiBytes // Glide default

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.mms
package org.signal.glide.common.io
import android.content.Context
import android.net.Uri

View File

@@ -16,7 +16,7 @@
* limitations under the License.
*/
package org.thoughtcrime.securesms.glide;
package org.signal.glide.common.io;
import androidx.annotation.NonNull;

View File

@@ -3,14 +3,15 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.glide
package org.signal.glide.load
import androidx.exifinterface.media.ExifInterface
import com.bumptech.glide.load.ImageHeaderParser
import com.bumptech.glide.load.data.ParcelFileDescriptorRewinder
import com.bumptech.glide.load.engine.bitmap_recycle.ArrayPool
import com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream
import org.thoughtcrime.securesms.mms.InputStreamFactory
import org.signal.glide.common.io.GlideStreamConfig
import org.signal.glide.common.io.InputStreamFactory
import org.thoughtcrime.securesms.util.BitmapUtil
import java.io.IOException
import java.io.InputStream

View File

@@ -2,7 +2,7 @@
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.glide.transforms
package org.signal.glide.load
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import kotlin.math.max

View File

@@ -3,17 +3,17 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng;
package org.signal.glide.load.resource.apng;
import android.content.Context;
import org.signal.glide.apng.decode.APNGDecoder;
import org.signal.glide.common.FrameAnimationDrawable;
import org.signal.glide.common.decode.FrameSeqDecoder;
import org.signal.glide.common.loader.AssetStreamLoader;
import org.signal.glide.common.loader.FileLoader;
import org.signal.glide.common.loader.Loader;
import org.signal.glide.common.loader.ResourceStreamLoader;
import org.signal.glide.load.resource.apng.decode.APNGDecoder;
/**
* @Description: APNGDrawable

View File

@@ -3,9 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.load.resource.apng.io.APNGReader;
import java.io.IOException;

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -13,12 +13,12 @@ import android.graphics.PorterDuff;
import android.graphics.Rect;
import org.signal.core.util.logging.Log;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.apng.io.APNGWriter;
import org.signal.glide.common.decode.Frame;
import org.signal.glide.common.decode.FrameSeqDecoder;
import org.signal.glide.common.io.Reader;
import org.signal.glide.common.loader.Loader;
import org.signal.glide.load.resource.apng.io.APNGReader;
import org.signal.glide.load.resource.apng.io.APNGWriter;
import java.io.IOException;
import java.nio.ByteBuffer;

View File

@@ -3,16 +3,16 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.apng.io.APNGWriter;
import org.signal.glide.common.decode.Frame;
import org.signal.glide.load.resource.apng.io.APNGReader;
import org.signal.glide.load.resource.apng.io.APNGWriter;
import java.io.IOException;
import java.util.ArrayList;

View File

@@ -3,13 +3,13 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import android.content.Context;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.common.io.Reader;
import org.signal.glide.common.io.StreamReader;
import org.signal.glide.load.resource.apng.io.APNGReader;
import java.io.FileInputStream;
import java.io.IOException;

View File

@@ -3,11 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import android.text.TextUtils;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.load.resource.apng.io.APNGReader;
import java.io.IOException;

View File

@@ -3,9 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.load.resource.apng.io.APNGReader;
import java.io.IOException;

View File

@@ -3,9 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.load.resource.apng.io.APNGReader;
import java.io.IOException;

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
/**
* @Description: 作用描述

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
/**
* @Description: 作用描述

View File

@@ -3,9 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.load.resource.apng.io.APNGReader;
import java.io.IOException;

View File

@@ -3,16 +3,16 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.decode;
package org.signal.glide.load.resource.apng.decode;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import org.signal.glide.apng.io.APNGReader;
import org.signal.glide.apng.io.APNGWriter;
import org.signal.glide.common.decode.Frame;
import org.signal.glide.load.resource.apng.io.APNGReader;
import org.signal.glide.load.resource.apng.io.APNGWriter;
import java.io.IOException;

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.io;
package org.signal.glide.load.resource.apng.io;
import android.text.TextUtils;

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.signal.glide.apng.io;
package org.signal.glide.load.resource.apng.io;
import org.signal.glide.common.io.ByteBufferWriter;

View File

@@ -16,7 +16,7 @@
* limitations under the License.
*/
package org.thoughtcrime.securesms.glide;
package org.signal.glide.load.resource.bitmap;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
@@ -53,7 +53,7 @@ import com.bumptech.glide.util.Preconditions;
import com.bumptech.glide.util.Util;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.mms.InputStreamFactory;
import org.signal.glide.common.io.InputStreamFactory;
import java.io.File;
import java.io.IOException;
@@ -228,13 +228,13 @@ public final class Downsampler {
* of the image for the given InputStream is available, the operation is much less expensive in
* terms of memory.
*
* @param inputStreamFactory An {@link InputStreamFactory} to the data for the image.
* @param requestedWidth The width the final image should be close to.
* @param requestedHeight The height the final image should be close to.
* @param options A set of options that may contain one or more supported options that influence
* how a Bitmap will be decoded from the given stream.
* @param callbacks A set of callbacks allowing callers to optionally respond to various
* significant events during the decode process.
* @param inputStreamFactory An {@link InputStreamFactory} to the data for the image.
* @param requestedWidth The width the final image should be close to.
* @param requestedHeight The height the final image should be close to.
* @param options A set of options that may contain one or more supported options that influence
* how a Bitmap will be decoded from the given stream.
* @param callbacks A set of callbacks allowing callers to optionally respond to various
* significant events during the decode process.
* @return A new bitmap containing the image from the given InputStream, or recycle if recycle is
* not null.
*/

View File

@@ -16,7 +16,7 @@
* limitations under the License.
*/
package org.thoughtcrime.securesms.glide;
package org.signal.glide.load.resource.bitmap;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.glide;
package org.signal.glide.load.resource.bitmap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -24,7 +24,9 @@ import com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream;
import com.bumptech.glide.util.ByteBufferUtil;
import com.bumptech.glide.util.Preconditions;
import org.thoughtcrime.securesms.mms.InputStreamFactory;
import org.signal.glide.common.io.InputStreamFactory;
import org.signal.glide.common.io.InputStreamRewinder;
import org.signal.glide.load.ImageHeaderParserUtils;
import java.io.File;
import java.io.FileInputStream;
@@ -173,8 +175,8 @@ interface ImageReader {
}
final class InputStreamImageReader implements ImageReader {
private final InputStreamRewinder dataRewinder;
private final ArrayPool byteArrayPool;
private final InputStreamRewinder dataRewinder;
private final ArrayPool byteArrayPool;
private final List<ImageHeaderParser> parsers;
private final InputStreamFactory inputStreamFactory;

View File

@@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencyProvider;
import org.thoughtcrime.securesms.emoji.EmojiSource;
import org.thoughtcrime.securesms.emoji.JumboEmoji;
import org.thoughtcrime.securesms.gcm.FcmFetchManager;
import org.thoughtcrime.securesms.glide.SignalGlideComponents;
import org.thoughtcrime.securesms.jobs.AccountConsistencyWorkerJob;
import org.thoughtcrime.securesms.jobs.BackupRefreshJob;
import org.thoughtcrime.securesms.jobs.BackupSubscriptionCheckJob;
@@ -83,7 +84,6 @@ import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
import org.thoughtcrime.securesms.logging.PersistentLogger;
import org.thoughtcrime.securesms.messageprocessingalarm.RoutineMessageFetchReceiver;
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
import org.thoughtcrime.securesms.mms.SignalGlideComponents;
import org.thoughtcrime.securesms.mms.SignalGlideModule;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.ratelimit.RateLimitUtil;
@@ -128,7 +128,7 @@ import rxdogtag2.RxDogTag;
/**
* Will be called once when the TextSecure process is created.
*
* <p>
* We're using this as an insertion point to patch up the Android PRNG disaster,
* to initialize the job manager, and to check for GCM registration freshness.
*
@@ -139,7 +139,7 @@ public class ApplicationContext extends Application implements AppForegroundObse
private static final String TAG = Log.tag(ApplicationContext.class);
public static ApplicationContext getInstance(Context context) {
return (ApplicationContext)context.getApplicationContext();
return (ApplicationContext) context.getApplicationContext();
}
@Override
@@ -153,82 +153,82 @@ public class ApplicationContext extends Application implements AppForegroundObse
super.onCreate();
AppStartup.getInstance().addBlocking("sqlcipher-init", () -> {
SqlCipherLibraryLoader.load();
SignalDatabase.init(this,
DatabaseSecretProvider.getOrCreateDatabaseSecret(this),
AttachmentSecretProvider.getInstance(this).getOrCreateAttachmentSecret());
})
.addBlocking("signal-store", () -> SignalStore.init(this))
.addBlocking("logging", () -> {
initializeLogging();
Log.i(TAG, "onCreate()");
})
.addBlocking("app-dependencies", this::initializeAppDependencies)
.addBlocking("anr-detector", this::startAnrDetector)
.addBlocking("security-provider", this::initializeSecurityProvider)
.addBlocking("crash-handling", this::initializeCrashHandling)
.addBlocking("rx-init", this::initializeRx)
.addBlocking("event-bus", () -> EventBus.builder().logNoSubscriberMessages(false).installDefaultEventBus())
.addBlocking("scrubber", () -> Scrubber.setIdentifierHmacKeyProvider(() -> SignalStore.svr().getMasterKey().deriveLoggingKey()))
.addBlocking("first-launch", this::initializeFirstEverAppLaunch)
.addBlocking("app-migrations", this::initializeApplicationMigrations)
.addBlocking("lifecycle-observer", () -> AppForegroundObserver.addListener(this))
.addBlocking("message-retriever", this::initializeMessageRetrieval)
.addBlocking("dynamic-theme", () -> DynamicTheme.setDefaultDayNightMode(this))
.addBlocking("proxy-init", () -> {
if (SignalStore.proxy().isProxyEnabled()) {
Log.w(TAG, "Proxy detected. Enabling Conscrypt.setUseEngineSocketByDefault()");
ConscryptSignal.setUseEngineSocketByDefault(true);
}
})
.addBlocking("blob-provider", this::initializeBlobProvider)
.addBlocking("remote-config", RemoteConfig::init)
.addBlocking("ring-rtc", this::initializeRingRtc)
.addBlocking("glide", () -> SignalGlideModule.setRegisterGlideComponents(new SignalGlideComponents()))
.addBlocking("tracer", this::initializeTracer)
.addNonBlocking(() -> RegistrationUtil.maybeMarkRegistrationComplete())
.addNonBlocking(() -> Glide.get(this))
.addNonBlocking(this::cleanAvatarStorage)
.addNonBlocking(this::initializeRevealableMessageManager)
.addNonBlocking(this::initializePendingRetryReceiptManager)
.addNonBlocking(this::initializeScheduledMessageManager)
.addNonBlocking(this::initializeFcmCheck)
.addNonBlocking(PreKeysSyncJob::enqueueIfNeeded)
.addNonBlocking(this::initializePeriodicTasks)
.addNonBlocking(this::initializeCircumvention)
.addNonBlocking(this::initializeCleanup)
.addNonBlocking(this::initializeGlideCodecs)
.addNonBlocking(StorageSyncHelper::scheduleRoutineSync)
.addNonBlocking(this::beginJobLoop)
.addNonBlocking(EmojiSource::refresh)
.addNonBlocking(() -> AppDependencies.getGiphyMp4Cache().onAppStart(this))
.addNonBlocking(AppDependencies::getBillingApi)
.addNonBlocking(this::ensureProfileUploaded)
.addNonBlocking(() -> AppDependencies.getExpireStoriesManager().scheduleIfNecessary())
.addPostRender(() -> AppDependencies.getDeletedCallEventManager().scheduleIfNecessary())
.addPostRender(() -> RateLimitUtil.retryAllRateLimitedMessages(this))
.addPostRender(this::initializeExpiringMessageManager)
.addPostRender(this::initializeTrimThreadsByDateManager)
.addPostRender(RefreshSvrCredentialsJob::enqueueIfNecessary)
.addPostRender(() -> DownloadLatestEmojiDataJob.scheduleIfNecessary(this))
.addPostRender(EmojiSearchIndexDownloadJob::scheduleIfNecessary)
.addPostRender(() -> SignalDatabase.messageLog().trimOldMessages(System.currentTimeMillis(), RemoteConfig.retryRespondMaxAge()))
.addPostRender(() -> JumboEmoji.updateCurrentVersion(this))
.addPostRender(RetrieveRemoteAnnouncementsJob::enqueue)
.addPostRender(() -> AndroidTelecomUtil.registerPhoneAccount())
.addPostRender(() -> AppDependencies.getJobManager().add(new FontDownloaderJob()))
.addPostRender(CheckServiceReachabilityJob::enqueueIfNecessary)
.addPostRender(GroupV2UpdateSelfProfileKeyJob::enqueueForGroupsIfNecessary)
.addPostRender(StoryOnboardingDownloadJob.Companion::enqueueIfNeeded)
.addPostRender(() -> AppDependencies.getExoPlayerPool().getPoolStats().getMaxUnreserved())
.addPostRender(() -> AppDependencies.getRecipientCache().warmUp())
.addPostRender(AccountConsistencyWorkerJob::enqueueIfNecessary)
.addPostRender(GroupRingCleanupJob::enqueue)
.addPostRender(LinkedDeviceInactiveCheckJob::enqueueIfNecessary)
.addPostRender(() -> ActiveCallManager.clearNotifications(this))
.addPostRender(RestoreOptimizedMediaJob::enqueueIfNecessary)
.addPostRender(RetryPendingSendsJob::enqueueForAll)
.execute();
SqlCipherLibraryLoader.load();
SignalDatabase.init(this,
DatabaseSecretProvider.getOrCreateDatabaseSecret(this),
AttachmentSecretProvider.getInstance(this).getOrCreateAttachmentSecret());
})
.addBlocking("signal-store", () -> SignalStore.init(this))
.addBlocking("logging", () -> {
initializeLogging();
Log.i(TAG, "onCreate()");
})
.addBlocking("app-dependencies", this::initializeAppDependencies)
.addBlocking("anr-detector", this::startAnrDetector)
.addBlocking("security-provider", this::initializeSecurityProvider)
.addBlocking("crash-handling", this::initializeCrashHandling)
.addBlocking("rx-init", this::initializeRx)
.addBlocking("event-bus", () -> EventBus.builder().logNoSubscriberMessages(false).installDefaultEventBus())
.addBlocking("scrubber", () -> Scrubber.setIdentifierHmacKeyProvider(() -> SignalStore.svr().getMasterKey().deriveLoggingKey()))
.addBlocking("first-launch", this::initializeFirstEverAppLaunch)
.addBlocking("app-migrations", this::initializeApplicationMigrations)
.addBlocking("lifecycle-observer", () -> AppForegroundObserver.addListener(this))
.addBlocking("message-retriever", this::initializeMessageRetrieval)
.addBlocking("dynamic-theme", () -> DynamicTheme.setDefaultDayNightMode(this))
.addBlocking("proxy-init", () -> {
if (SignalStore.proxy().isProxyEnabled()) {
Log.w(TAG, "Proxy detected. Enabling Conscrypt.setUseEngineSocketByDefault()");
ConscryptSignal.setUseEngineSocketByDefault(true);
}
})
.addBlocking("blob-provider", this::initializeBlobProvider)
.addBlocking("remote-config", RemoteConfig::init)
.addBlocking("ring-rtc", this::initializeRingRtc)
.addBlocking("glide", () -> SignalGlideModule.setRegisterGlideComponents(new SignalGlideComponents()))
.addBlocking("tracer", this::initializeTracer)
.addNonBlocking(() -> RegistrationUtil.maybeMarkRegistrationComplete())
.addNonBlocking(() -> Glide.get(this))
.addNonBlocking(this::cleanAvatarStorage)
.addNonBlocking(this::initializeRevealableMessageManager)
.addNonBlocking(this::initializePendingRetryReceiptManager)
.addNonBlocking(this::initializeScheduledMessageManager)
.addNonBlocking(this::initializeFcmCheck)
.addNonBlocking(PreKeysSyncJob::enqueueIfNeeded)
.addNonBlocking(this::initializePeriodicTasks)
.addNonBlocking(this::initializeCircumvention)
.addNonBlocking(this::initializeCleanup)
.addNonBlocking(this::initializeGlideCodecs)
.addNonBlocking(StorageSyncHelper::scheduleRoutineSync)
.addNonBlocking(this::beginJobLoop)
.addNonBlocking(EmojiSource::refresh)
.addNonBlocking(() -> AppDependencies.getGiphyMp4Cache().onAppStart(this))
.addNonBlocking(AppDependencies::getBillingApi)
.addNonBlocking(this::ensureProfileUploaded)
.addNonBlocking(() -> AppDependencies.getExpireStoriesManager().scheduleIfNecessary())
.addPostRender(() -> AppDependencies.getDeletedCallEventManager().scheduleIfNecessary())
.addPostRender(() -> RateLimitUtil.retryAllRateLimitedMessages(this))
.addPostRender(this::initializeExpiringMessageManager)
.addPostRender(this::initializeTrimThreadsByDateManager)
.addPostRender(RefreshSvrCredentialsJob::enqueueIfNecessary)
.addPostRender(() -> DownloadLatestEmojiDataJob.scheduleIfNecessary(this))
.addPostRender(EmojiSearchIndexDownloadJob::scheduleIfNecessary)
.addPostRender(() -> SignalDatabase.messageLog().trimOldMessages(System.currentTimeMillis(), RemoteConfig.retryRespondMaxAge()))
.addPostRender(() -> JumboEmoji.updateCurrentVersion(this))
.addPostRender(RetrieveRemoteAnnouncementsJob::enqueue)
.addPostRender(() -> AndroidTelecomUtil.registerPhoneAccount())
.addPostRender(() -> AppDependencies.getJobManager().add(new FontDownloaderJob()))
.addPostRender(CheckServiceReachabilityJob::enqueueIfNecessary)
.addPostRender(GroupV2UpdateSelfProfileKeyJob::enqueueForGroupsIfNecessary)
.addPostRender(StoryOnboardingDownloadJob.Companion::enqueueIfNeeded)
.addPostRender(() -> AppDependencies.getExoPlayerPool().getPoolStats().getMaxUnreserved())
.addPostRender(() -> AppDependencies.getRecipientCache().warmUp())
.addPostRender(AccountConsistencyWorkerJob::enqueueIfNecessary)
.addPostRender(GroupRingCleanupJob::enqueue)
.addPostRender(LinkedDeviceInactiveCheckJob::enqueueIfNecessary)
.addPostRender(() -> ActiveCallManager.clearNotifications(this))
.addPostRender(RestoreOptimizedMediaJob::enqueueIfNecessary)
.addPostRender(RetryPendingSendsJob::enqueueForAll)
.execute();
Log.d(TAG, "onCreate() took " + (System.currentTimeMillis() - startTime) + " ms");
SignalLocalMetrics.ColdStart.onApplicationCreateFinished();

View File

@@ -8,15 +8,14 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.badges.glide.BadgeSpriteTransformation
import org.thoughtcrime.securesms.badges.load.BadgeSpriteTransformation
import org.thoughtcrime.securesms.badges.load.GiftBadgeModel
import org.thoughtcrime.securesms.badges.models.Badge
import org.thoughtcrime.securesms.components.settings.app.subscription.BadgeImageSize
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
import org.thoughtcrime.securesms.glide.GiftBadgeModel
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.ScreenDensity
import org.thoughtcrime.securesms.util.ThemeUtil
import org.thoughtcrime.securesms.util.visible
class BadgeImageView @JvmOverloads constructor(
context: Context,

View File

@@ -1,4 +1,9 @@
package org.thoughtcrime.securesms.glide;
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.badges.load;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -11,6 +16,7 @@ import com.bumptech.glide.load.model.MultiModelLoaderFactory;
import org.thoughtcrime.securesms.badges.models.Badge;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.glide.OkHttpStreamFetcher;
import java.io.InputStream;

View File

@@ -1,4 +1,9 @@
package org.thoughtcrime.securesms.badges.glide
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.badges.load
import android.graphics.Bitmap
import android.graphics.Canvas

View File

@@ -1,4 +1,9 @@
package org.thoughtcrime.securesms.glide
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.badges.load
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
@@ -14,6 +19,7 @@ import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialPresentation
import org.thoughtcrime.securesms.components.settings.app.subscription.getBadge
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.glide.OkHttpStreamFetcher
import java.io.InputStream
import java.security.MessageDigest
import java.util.Locale

View File

@@ -13,7 +13,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
import kotlinx.parcelize.Parcelize
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.badges.glide.BadgeSpriteTransformation
import org.thoughtcrime.securesms.badges.load.BadgeSpriteTransformation
import org.thoughtcrime.securesms.components.settings.PreferenceModel
import org.thoughtcrime.securesms.util.ThemeUtil
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory

View File

@@ -39,13 +39,15 @@ import com.bumptech.glide.request.RequestOptions;
import org.signal.core.util.concurrent.ListenableFuture;
import org.signal.core.util.concurrent.SettableFuture;
import org.signal.core.util.logging.Log;
import org.signal.glide.transforms.SignalDownsampleStrategy;
import org.signal.glide.load.SignalDownsampleStrategy;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.blurhash.BlurHash;
import org.thoughtcrime.securesms.components.transfercontrols.TransferControlView;
import org.thoughtcrime.securesms.database.AttachmentTable;
import org.thoughtcrime.securesms.glide.targets.GlideBitmapListeningTarget;
import org.thoughtcrime.securesms.glide.targets.GlideDrawableListeningTarget;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mms.DecryptableUri;
import org.thoughtcrime.securesms.mms.ImageSlide;

View File

@@ -1,4 +1,9 @@
package org.thoughtcrime.securesms.glide;
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.contacts.avatars;
import android.content.Context;
@@ -9,8 +14,6 @@ import com.bumptech.glide.Priority;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.data.DataFetcher;
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

View File

@@ -1,4 +1,9 @@
package org.thoughtcrime.securesms.glide;
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.contacts.avatars;
import android.content.Context;
@@ -10,8 +15,6 @@ import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
import java.io.InputStream;
public class ContactPhotoLoader implements ModelLoader<ContactPhoto, InputStream> {

View File

@@ -1,4 +1,9 @@
package org.thoughtcrime.securesms.mms;
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.contacts.avatars;
import android.content.ContentResolver;
import android.content.Context;

View File

@@ -72,7 +72,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.database.model.UpdateDescription;
import org.thoughtcrime.securesms.fonts.SignalSymbols.Glyph;
import org.thoughtcrime.securesms.glide.GlideLiveDataTarget;
import org.thoughtcrime.securesms.glide.targets.GlideLiveDataTarget;
import org.thoughtcrime.securesms.mms.DecryptableUri;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient;

View File

@@ -1,3 +1,8 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.glide;
import androidx.annotation.NonNull;
@@ -8,8 +13,6 @@ import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.util.ContentLengthInputStream;
import org.signal.core.util.logging.Log;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
@@ -22,16 +25,14 @@ import okhttp3.ResponseBody;
/**
* Fetches an {@link InputStream} using the okhttp library.
*/
class OkHttpStreamFetcher implements DataFetcher<InputStream> {
private static final String TAG = Log.tag(OkHttpStreamFetcher.class);
public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
private final OkHttpClient client;
private final GlideUrl url;
private InputStream stream;
private ResponseBody responseBody;
OkHttpStreamFetcher(OkHttpClient client, GlideUrl url) {
public OkHttpStreamFetcher(OkHttpClient client, GlideUrl url) {
this.client = client;
this.url = url;
}

View File

@@ -1,9 +1,4 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.mms;
package org.thoughtcrime.securesms.glide;
import android.content.Context;
import android.graphics.Bitmap;
@@ -21,20 +16,19 @@ import com.bumptech.glide.load.resource.gif.ByteBufferGifDecoder;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.load.resource.gif.StreamGifDecoder;
import org.signal.glide.apng.decode.APNGDecoder;
import org.signal.glide.common.io.InputStreamFactory;
import org.signal.glide.load.resource.apng.decode.APNGDecoder;
import org.thoughtcrime.securesms.badges.load.BadgeLoader;
import org.thoughtcrime.securesms.badges.load.GiftBadgeModel;
import org.thoughtcrime.securesms.badges.models.Badge;
import org.thoughtcrime.securesms.blurhash.BlurHash;
import org.thoughtcrime.securesms.blurhash.BlurHashModelLoader;
import org.thoughtcrime.securesms.blurhash.BlurHashResourceDecoder;
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoLoader;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.giph.model.ChunkedImageUrl;
import org.thoughtcrime.securesms.glide.BadgeLoader;
import org.thoughtcrime.securesms.glide.ChunkedImageUrlLoader;
import org.thoughtcrime.securesms.glide.ContactPhotoLoader;
import org.thoughtcrime.securesms.glide.GiftBadgeModel;
import org.thoughtcrime.securesms.glide.OkHttpUrlLoader;
import org.thoughtcrime.securesms.glide.cache.ApngFrameDrawableTranscoder;
import org.thoughtcrime.securesms.glide.cache.ByteBufferApngDecoder;
import org.thoughtcrime.securesms.glide.cache.EncryptedApngCacheEncoder;
@@ -42,11 +36,16 @@ import org.thoughtcrime.securesms.glide.cache.EncryptedBitmapResourceEncoder;
import org.thoughtcrime.securesms.glide.cache.EncryptedCacheDecoder;
import org.thoughtcrime.securesms.glide.cache.EncryptedCacheEncoder;
import org.thoughtcrime.securesms.glide.cache.EncryptedGifDrawableResourceEncoder;
import org.thoughtcrime.securesms.glide.cache.InputStreamFactoryBitmapDecoder;
import org.thoughtcrime.securesms.glide.cache.StreamApngDecoder;
import org.thoughtcrime.securesms.glide.cache.StreamBitmapDecoder;
import org.thoughtcrime.securesms.glide.cache.StreamFactoryApngDecoder;
import org.thoughtcrime.securesms.glide.cache.StreamFactoryGifDecoder;
import org.thoughtcrime.securesms.glide.cache.WebpSanDecoder;
import org.thoughtcrime.securesms.mms.DecryptableUri;
import org.thoughtcrime.securesms.mms.DecryptableUriStreamLoader;
import org.thoughtcrime.securesms.mms.RegisterGlideComponents;
import org.thoughtcrime.securesms.mms.SignalGlideModule;
import org.thoughtcrime.securesms.stickers.StickerRemoteUri;
import org.thoughtcrime.securesms.stickers.StickerRemoteUriLoader;
import org.thoughtcrime.securesms.stories.StoryTextPostModel;

View File

@@ -10,8 +10,8 @@ import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.resource.drawable.DrawableResource;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
import org.signal.glide.apng.APNGDrawable;
import org.signal.glide.apng.decode.APNGDecoder;
import org.signal.glide.load.resource.apng.APNGDrawable;
import org.signal.glide.load.resource.apng.decode.APNGDecoder;
public class ApngFrameDrawableTranscoder implements ResourceTranscoder<APNGDecoder, Drawable> {

View File

@@ -7,11 +7,11 @@ import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import org.signal.glide.apng.decode.APNGDecoder;
import org.signal.glide.apng.decode.APNGParser;
import org.signal.glide.common.io.ByteBufferReader;
import org.signal.glide.common.loader.ByteBufferLoader;
import org.signal.glide.common.loader.Loader;
import org.signal.glide.load.resource.apng.decode.APNGDecoder;
import org.signal.glide.load.resource.apng.decode.APNGParser;
import java.io.IOException;
import java.nio.ByteBuffer;

View File

@@ -9,8 +9,8 @@ import com.bumptech.glide.load.engine.Resource;
import org.signal.core.util.StreamUtil;
import org.signal.core.util.logging.Log;
import org.signal.glide.apng.decode.APNGDecoder;
import org.signal.glide.common.loader.Loader;
import org.signal.glide.load.resource.apng.decode.APNGDecoder;
import java.io.File;
import java.io.IOException;

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.mms
package org.thoughtcrime.securesms.glide.cache
import android.content.Context
import android.graphics.Bitmap
@@ -12,7 +12,8 @@ import com.bumptech.glide.Registry
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.ResourceDecoder
import com.bumptech.glide.load.engine.Resource
import org.thoughtcrime.securesms.glide.Downsampler
import org.signal.glide.common.io.InputStreamFactory
import org.signal.glide.load.resource.bitmap.Downsampler
/**
* A Glide [ResourceDecoder] that decodes [Bitmap]s from a [InputStreamFactory] instances.

View File

@@ -8,9 +8,9 @@ import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import org.signal.core.util.StreamUtil;
import org.signal.glide.apng.decode.APNGDecoder;
import org.signal.glide.apng.decode.APNGParser;
import org.signal.glide.common.io.StreamReader;
import org.signal.glide.load.resource.apng.decode.APNGDecoder;
import org.signal.glide.load.resource.apng.decode.APNGParser;
import java.io.IOException;
import java.io.InputStream;

View File

@@ -12,9 +12,9 @@ import com.bumptech.glide.load.Options
import com.bumptech.glide.load.ResourceDecoder
import com.bumptech.glide.load.engine.Resource
import org.signal.core.util.StreamUtil
import org.signal.glide.apng.decode.APNGDecoder
import org.thoughtcrime.securesms.glide.ImageHeaderParserUtils
import org.thoughtcrime.securesms.mms.InputStreamFactory
import org.signal.glide.common.io.InputStreamFactory
import org.signal.glide.load.ImageHeaderParserUtils
import org.signal.glide.load.resource.apng.decode.APNGDecoder
import java.nio.ByteBuffer
/**

View File

@@ -10,7 +10,7 @@ import com.bumptech.glide.load.ResourceDecoder
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.gif.GifDrawable
import com.bumptech.glide.load.resource.gif.StreamGifDecoder
import org.thoughtcrime.securesms.mms.InputStreamFactory
import org.signal.glide.common.io.InputStreamFactory
/**
* A variant of [StreamGifDecoder] that decodes animated PNGs from [InputStreamFactory] sources.

View File

@@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.components;
package org.thoughtcrime.securesms.glide.targets;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;

View File

@@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.components;
package org.thoughtcrime.securesms.glide.targets;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;

View File

@@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.glide;
package org.thoughtcrime.securesms.glide.targets;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;

View File

@@ -9,6 +9,7 @@ import android.content.Context
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.data.DataFetcher
import org.signal.glide.common.io.InputStreamFactory
/**
* A Glide [DataFetcher] that retrieves an [InputStreamFactory] for a [DecryptableUri].

View File

@@ -11,6 +11,7 @@ import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
import org.signal.glide.common.io.InputStreamFactory
/**
* A Glide [ModelLoader] that handles conversion from [DecryptableUri] to [InputStreamFactory].