From 1fcac2cf4e2e64218ceff2fa0194dc43e1c1c819 Mon Sep 17 00:00:00 2001 From: Achraf Feydi Date: Tue, 26 Sep 2023 11:00:15 +0000 Subject: Make BoundDynamicTypeImpl#close method idempotent BUG: 300603668 (cherry picked from https://android-review.googlesource.com/q/commit:542cefebc406ba6494e4854a62fb5c194ceaf2e4) Merged-In: I037d7aaa1f6d911e4b94662ea02904101c316c53 Change-Id: I037d7aaa1f6d911e4b94662ea02904101c316c53 --- .../expression/pipeline/BoundDynamicTypeImpl.java | 13 +++++++++++++ .../expression/pipeline/DynamicTypeEvaluatorTest.java | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/BoundDynamicTypeImpl.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/BoundDynamicTypeImpl.java index bbae3dce988..4481752f703 100644 --- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/BoundDynamicTypeImpl.java +++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/BoundDynamicTypeImpl.java @@ -18,6 +18,7 @@ package androidx.wear.protolayout.expression.pipeline; import android.os.Handler; import android.os.Looper; +import android.util.Log; import androidx.annotation.UiThread; @@ -28,8 +29,11 @@ import java.util.List; * evaluation. */ class BoundDynamicTypeImpl implements BoundDynamicType { + private static final String TAG = "BoundDynamicTypeImpl"; + private final List> mNodes; private final QuotaManager mDynamicDataNodesQuotaManager; + private boolean mIsClosed = false; BoundDynamicTypeImpl( List> nodes, QuotaManager dynamicDataNodesQuotaManager) { @@ -88,8 +92,17 @@ class BoundDynamicTypeImpl implements BoundDynamicType { } } + /** + * Closes this {@link BoundDynamicTypeImpl} instance and releases any allocated quota. This + * method must be called only once on each {@link BoundDynamicTypeImpl} instance. + */ @UiThread private void closeInternal() { + if (mIsClosed) { + Log.w(TAG, "close() method was called more than once."); + return; + } + mIsClosed = true; mNodes.stream() .filter(n -> n instanceof DynamicDataSourceNode) .forEach(n -> ((DynamicDataSourceNode) n).destroy()); diff --git a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java index d1fcf4cc91b..ae0ab5a896e 100644 --- a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java +++ b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/DynamicTypeEvaluatorTest.java @@ -132,6 +132,22 @@ public class DynamicTypeEvaluatorTest { verify(provider).clearReceiver(); } + @Test + public void closeCalledMultipleTimesOnBoundDynamicType_doesNotThrow() + throws EvaluationException { + DynamicTypeEvaluator evaluator = + createEvaluatorWithQuota( + /* animationQuota= */ unlimitedQuota(), + /* dynamicTypesQuota= */ new FixedQuotaManagerImpl(1)); + ArrayList results = new ArrayList<>(); + BoundDynamicType boundDynamicType = evaluator.bind( + createSingleNodeDynamicBoolRequest(results)); + + for (int i = 0; i < 10; i++) { + boundDynamicType.close(); + } + } + @NonNull private static DynamicTypeBindingRequest createSingleNodeDynamicBoolRequest( ArrayList results) { -- cgit v1.2.3