From 2e1e19120fb5e5b421c7154cde35079a41f32d22 Mon Sep 17 00:00:00 2001 From: Fares Alhassen Date: Fri, 10 Oct 2025 13:47:16 -0700 Subject: [PATCH] to remove PiperOrigin-RevId: 817774267 --- .../com/bumptech/glide/MultiRequestTest.java | 3 ++- .../java/com/bumptech/glide/RequestTest.java | 5 ++++- .../java/com/bumptech/glide/GlideBuilder.java | 16 ++++++++++++++++ .../java/com/bumptech/glide/RequestBuilder.java | 10 +++++++++- .../glide/request/SingleRequestTest.java | 3 +++ 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/instrumentation/src/androidTest/java/com/bumptech/glide/MultiRequestTest.java b/instrumentation/src/androidTest/java/com/bumptech/glide/MultiRequestTest.java index cd5948b8ad..6ac316f8b8 100644 --- a/instrumentation/src/androidTest/java/com/bumptech/glide/MultiRequestTest.java +++ b/instrumentation/src/androidTest/java/com/bumptech/glide/MultiRequestTest.java @@ -53,7 +53,8 @@ public void thumbnail_onResourceReady_forPrimary_isComplete_whenRequestListenerI Glide.init( context, new GlideBuilder() - .setSourceExecutor(GlideExecutor.newSourceBuilder().setThreadCount(1).build())); + .setSourceExecutor(GlideExecutor.newSourceBuilder().setThreadCount(1).build()) + .setFixSingleRequestClearDeadlock(true)); AtomicBoolean isPrimaryRequestComplete = new AtomicBoolean(false); CountDownLatch countDownLatch = new CountDownLatch(1); diff --git a/instrumentation/src/androidTest/java/com/bumptech/glide/RequestTest.java b/instrumentation/src/androidTest/java/com/bumptech/glide/RequestTest.java index 0a08ad363e..6990425f3e 100644 --- a/instrumentation/src/androidTest/java/com/bumptech/glide/RequestTest.java +++ b/instrumentation/src/androidTest/java/com/bumptech/glide/RequestTest.java @@ -50,7 +50,10 @@ public void setUp() { // Some emulators only have a single resize thread, so waiting on a latch will block them // forever. Glide.init( - context, new GlideBuilder().setSourceExecutor(GlideExecutor.newUnlimitedSourceExecutor())); + context, + new GlideBuilder() + .setSourceExecutor(GlideExecutor.newUnlimitedSourceExecutor()) + .setFixSingleRequestClearDeadlock(true)); } @Test diff --git a/library/src/main/java/com/bumptech/glide/GlideBuilder.java b/library/src/main/java/com/bumptech/glide/GlideBuilder.java index 94a774122a..38e9b1628a 100644 --- a/library/src/main/java/com/bumptech/glide/GlideBuilder.java +++ b/library/src/main/java/com/bumptech/glide/GlideBuilder.java @@ -539,6 +539,19 @@ public GlideBuilder setDisableHardwareBitmapsOnO(boolean disableHardwareBitmapsO return this; } + /** + * Fix single request clear deadlock mentioned in #5617. + * + *

This flag changes {@link com.bumptech.glide.request.SingleRequest} to lock on underlying + * {@link Engine} to avoid deadlocks in calling code that also requires a lock on the {@link + * Engine}. + */ + public GlideBuilder setFixSingleRequestClearDeadlock(boolean isEnabled) { + glideExperimentsBuilder.update(new FixSingleRequestClearDeadlock(), isEnabled); + return this; + } + void setRequestManagerFactory(@Nullable RequestManagerFactory factory) { this.requestManagerFactory = factory; } @@ -653,4 +666,7 @@ public static final class OverrideGlideThreadPriority implements Experiment {} /** See {@link #setUseMediaStoreOpenFileApisIfPossible(boolean)}. */ public static final class UseMediaStoreOpenFileApisIfPossible implements Experiment {} + + /** See {@link #setFixSingleRequestClearDeadlock(boolean)}. */ + public static final class FixSingleRequestClearDeadlock implements Experiment {} } diff --git a/library/src/main/java/com/bumptech/glide/RequestBuilder.java b/library/src/main/java/com/bumptech/glide/RequestBuilder.java index 2eded8d99c..9a72f5688c 100644 --- a/library/src/main/java/com/bumptech/glide/RequestBuilder.java +++ b/library/src/main/java/com/bumptech/glide/RequestBuilder.java @@ -16,6 +16,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RawRes; +import com.bumptech.glide.GlideBuilder.FixSingleRequestClearDeadlock; import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.Transformation; import com.bumptech.glide.load.engine.DiskCacheStrategy; @@ -68,6 +69,7 @@ public class RequestBuilder extends BaseRequestOptions transcodeClass; private final Glide glide; private final GlideContext glideContext; + private final GlideExperiments experiments; @NonNull @SuppressWarnings("unchecked") @@ -99,6 +101,7 @@ protected RequestBuilder( this.context = context; this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass); this.glideContext = glide.getGlideContext(); + this.experiments = glide.getGlideContext().getExperiments(); initRequestListeners(requestManager.getDefaultRequestListeners()); apply(requestManager.getDefaultRequestOptions()); @@ -1166,8 +1169,13 @@ private Request buildRequest( @Nullable RequestListener targetListener, BaseRequestOptions requestOptions, Executor callbackExecutor) { + GlideExperiments experiments = glideContext.getExperiments(); + Object requestLock = + glideContext.getExperiments().isEnabled(FixSingleRequestClearDeadlock.class) + ? glideContext.getEngine() + : new Object(); return buildRequestRecursive( - /* requestLock= */ new Object(), + requestLock, target, targetListener, /* parentCoordinator= */ null, diff --git a/library/test/src/test/java/com/bumptech/glide/request/SingleRequestTest.java b/library/test/src/test/java/com/bumptech/glide/request/SingleRequestTest.java index 6f6a4a6765..cdd8946071 100644 --- a/library/test/src/test/java/com/bumptech/glide/request/SingleRequestTest.java +++ b/library/test/src/test/java/com/bumptech/glide/request/SingleRequestTest.java @@ -23,6 +23,7 @@ import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.bumptech.glide.GlideBuilder.FixSingleRequestClearDeadlock; import com.bumptech.glide.GlideContext; import com.bumptech.glide.GlideExperiments; import com.bumptech.glide.Priority; @@ -1071,6 +1072,8 @@ static final class SingleRequestBuilder { private final Map, Transformation> transformations = new HashMap<>(); SingleRequestBuilder() { + GlideExperiments glideExperiments = mock(GlideExperiments.class); + when(glideExperiments.isEnabled(FixSingleRequestClearDeadlock.class)).thenReturn(true); when(glideContext.getExperiments()).thenReturn(mock(GlideExperiments.class)); when(requestCoordinator.getRoot()).thenReturn(requestCoordinator); when(requestCoordinator.canSetImage(any(Request.class))).thenReturn(true);