From e19658ac3657d113ffdb7ccd4b3d56c1e8440a77 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Fri, 4 Jan 2019 15:12:19 +0800 Subject: [PATCH] Fix ConcurrentModificationException in SliceBackgroundWorker - Two different threads could call SliceBackgroundWorker.getInstance() at the same time and caused ConcurrentModificationException - Add a new API overloading getInstance for each slice to get a nullable worker since there is no result data then - Only slice provider can create a new worker instance in main thread Test: robotest Change-Id: I560529bb6034ec22263418adeb7f3ccebf879196 Fixes: 121043385 --- .../slices/BatteryFixSlice.java | 4 ++-- .../slices/SliceBackgroundWorker.java | 20 ++++++++++++++----- .../settings/wifi/slice/WifiSlice.java | 4 ++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java index ab1b4c90327..531501b3b5e 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java +++ b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java @@ -82,8 +82,8 @@ public class BatteryFixSlice implements CustomSliceable { return buildBatteryGoodSlice(sliceBuilder, true); } - final List batteryTips = SliceBackgroundWorker.getInstance(mContext, - this).getResults(); + final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri()); + final List batteryTips = worker != null ? worker.getResults() : null; if (batteryTips == null) { // Because we need wait slice background worker return data diff --git a/src/com/android/settings/slices/SliceBackgroundWorker.java b/src/com/android/settings/slices/SliceBackgroundWorker.java index 8b68f057ec0..284fd23466d 100644 --- a/src/com/android/settings/slices/SliceBackgroundWorker.java +++ b/src/com/android/settings/slices/SliceBackgroundWorker.java @@ -17,6 +17,7 @@ package com.android.settings.slices; import android.annotation.MainThread; +import android.annotation.Nullable; import android.content.Context; import android.net.Uri; import android.util.ArrayMap; @@ -58,20 +59,29 @@ public abstract class SliceBackgroundWorker implements Closeable { mUri = uri; } - public Uri getUri() { + protected Uri getUri() { return mUri; } + /** + * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link Uri} + * if exists + */ + @Nullable + public static SliceBackgroundWorker getInstance(Uri uri) { + return LIVE_WORKERS.get(uri); + } + /** * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link * CustomSliceable} */ - public static SliceBackgroundWorker getInstance(Context context, CustomSliceable sliceable) { + static SliceBackgroundWorker getInstance(Context context, CustomSliceable sliceable) { final Uri uri = sliceable.getUri(); - final Class workerClass = - sliceable.getBackgroundWorkerClass(); - SliceBackgroundWorker worker = LIVE_WORKERS.get(uri); + SliceBackgroundWorker worker = getInstance(uri); if (worker == null) { + final Class workerClass = + sliceable.getBackgroundWorkerClass(); worker = createInstance(context, uri, workerClass); LIVE_WORKERS.put(uri, worker); } diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java index 4d3a95ad217..35bb89f0111 100644 --- a/src/com/android/settings/wifi/slice/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -105,8 +105,8 @@ public class WifiSlice implements CustomSliceable { return listBuilder.build(); } - final List results = - SliceBackgroundWorker.getInstance(mContext, this).getResults(); + final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri()); + final List results = worker != null ? worker.getResults() : null; // Need a loading text when results are not ready. boolean needLoadingRow = results == null;