From 73afb042dc3e6359f0d3350bc25038c5f26d0826 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Sun, 21 Jun 2020 17:06:53 +0800 Subject: [PATCH] Workaround of Slice not pinned bug when using SliceCallback When a client registers a SliceCallback, it starts to observe Slice changes. The observer is running in the main looper and binds Slice in AsyncTask. However, when the client unregisters the callback, it unpins the Slice in the client's thread. Thus, if the AsyncTask has pinned the slice but hasn't bound it yet, it may be unpinned by the client, and an exception occurs. This fix is to unpin the Slice in the same SerialExecutor of AsyncTask, which is to ensure bindSlice() and unpinSlice() are called in the same thread one after another without the race condition. Bug: 157387583 Test: robotest Change-Id: If5f4b4bc0d8c5a2800cad8ff2afd7084426a6c96 --- .../homepage/contextualcards/EligibleCardChecker.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java index 43403306cb3..46b4c869ecb 100644 --- a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java +++ b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java @@ -22,6 +22,7 @@ import android.app.settings.SettingsEnums; import android.content.ContentResolver; import android.content.Context; import android.net.Uri; +import android.os.AsyncTask; import android.util.Log; import androidx.annotation.VisibleForTesting; @@ -32,6 +33,7 @@ import androidx.slice.core.SliceAction; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.android.settingslib.utils.ThreadUtils; import java.util.List; import java.util.concurrent.Callable; @@ -115,7 +117,12 @@ public class EligibleCardChecker implements Callable { // Register a trivial callback to pin the slice manager.registerSliceCallback(uri, callback); final Slice slice = manager.bindSlice(uri); - manager.unregisterSliceCallback(uri, callback); + + // Workaround of unpinning slice in the same SerialExecutor of AsyncTask as SliceCallback's + // observer. + ThreadUtils.postOnMainThread(() -> + AsyncTask.execute(() -> manager.unregisterSliceCallback(uri, callback)) + ); return slice; }