Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7afded1 authored by Jason Chiu's avatar Jason Chiu
Browse files

Fix Slice not pinned error

Slices should be pinned before being bound. The original design calls
registerSliceCallback() to pin a slice, and then calls bindSlice() and
passes the result to the callback directly. When the callback is
called, it executes unregisterSliceCallback() and unpins the slice.

However, registerSliceCallback() starts to observe the slice change and
then rebind it in an AsyncTask. If the slice is updating via its
background worker and the timing of the binding overlaps the callback
execution, it's possible to bind the slice right after unpinning it and
causes the error.

The solution is to remove the callback mechanism, and just to pin, bind
and unpin the slice directly.

Fixes: 157387583
Test: robotest
Change-Id: I8748dd3038a3662599935f07420d07cf254a4073
parent 03b20f86
Loading
Loading
Loading
Loading
+5 −33
Original line number Diff line number Diff line
@@ -35,13 +35,10 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class EligibleCardChecker implements Callable<ContextualCard> {

    private static final String TAG = "EligibleCardChecker";
    private static final long LATCH_TIMEOUT_MS = 300;

    private final Context mContext;

@@ -54,7 +51,7 @@ public class EligibleCardChecker implements Callable<ContextualCard> {
    }

    @Override
    public ContextualCard call() throws Exception {
    public ContextualCard call() {
        final long startTime = System.currentTimeMillis();
        final MetricsFeatureProvider metricsFeatureProvider =
                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
@@ -113,35 +110,10 @@ public class EligibleCardChecker implements Callable<ContextualCard> {
    @VisibleForTesting
    Slice bindSlice(Uri uri) {
        final SliceViewManager manager = SliceViewManager.getInstance(mContext);
        final Slice[] returnSlice = new Slice[1];
        final CountDownLatch latch = new CountDownLatch(1);
        final SliceViewManager.SliceCallback callback =
                new SliceViewManager.SliceCallback() {
                    @Override
                    public void onSliceUpdated(Slice slice) {
                        try {
                            // We are just making sure the existence of the slice, so ignore
                            // slice loading state here.
                            returnSlice[0] = slice;
                            latch.countDown();
                        } catch (Exception e) {
                            Log.w(TAG, uri + " cannot be indexed", e);
                        } finally {
                            manager.unregisterSliceCallback(uri, this);
                        }
                    }
                };
        // Register a callback until we get a loaded slice.
        manager.registerSliceCallback(uri, callback);
        // Trigger the binding.
        callback.onSliceUpdated(manager.bindSlice(uri));
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Log.w(TAG, "Error waiting for slice binding for uri" + uri, e);
            manager.unregisterSliceCallback(uri, callback);
        }
        return returnSlice[0];
        manager.pinSlice(uri);
        final Slice slice = manager.bindSlice(uri);
        manager.unpinSlice(uri);
        return slice;
    }

    @VisibleForTesting
+2 −2
Original line number Diff line number Diff line
@@ -77,9 +77,9 @@ public class EligibleCardCheckerTest {

    @Test
    public void isCardEligibleToDisplay_invalidScheme_returnFalse() {
        final Uri sliceUri = Uri.parse("contet://com.android.settings.slices/action/flashlight");
        final Uri invalidUri = Uri.parse("contet://com.android.settings.slices/action/flashlight");

        assertThat(mEligibleCardChecker.isCardEligibleToDisplay(getContextualCard(sliceUri)))
        assertThat(mEligibleCardChecker.isCardEligibleToDisplay(getContextualCard(invalidUri)))
                .isFalse();
    }

+2 −2
Original line number Diff line number Diff line
@@ -86,10 +86,10 @@ public class SliceContextualCardRendererTest {

    @Test
    public void bindView_invalidScheme_sliceShouldBeNull() {
        final Uri sliceUri = Uri.parse("contet://com.android.settings.slices/action/flashlight");
        final Uri invalidUri = Uri.parse("contet://com.android.settings.slices/action/flashlight");
        final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();

        mRenderer.bindView(viewHolder, buildContextualCard(sliceUri));
        mRenderer.bindView(viewHolder, buildContextualCard(invalidUri));

        assertThat(
                ((SliceFullCardRendererHelper.SliceViewHolder) viewHolder).sliceView.getSlice())