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
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
index ab1b4c9..531501b 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 @@
             return buildBatteryGoodSlice(sliceBuilder, true);
         }
 
-        final List<BatteryTip> batteryTips = SliceBackgroundWorker.getInstance(mContext,
-                this).getResults();
+        final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri());
+        final List<BatteryTip> 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 8b68f05..284fd23 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 @@
         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<? extends SliceBackgroundWorker> workerClass =
-                sliceable.getBackgroundWorkerClass();
-        SliceBackgroundWorker worker = LIVE_WORKERS.get(uri);
+        SliceBackgroundWorker worker = getInstance(uri);
         if (worker == null) {
+            final Class<? extends SliceBackgroundWorker> 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 4d3a95a..35bb89f 100644
--- a/src/com/android/settings/wifi/slice/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -105,8 +105,8 @@
             return listBuilder.build();
         }
 
-        final List<AccessPoint> results =
-                SliceBackgroundWorker.getInstance(mContext, this).getResults();
+        final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri());
+        final List<AccessPoint> results = worker != null ? worker.getResults() : null;
 
         // Need a loading text when results are not ready.
         boolean needLoadingRow = results == null;