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

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

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
parent 6be224a9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -82,8 +82,8 @@ public class BatteryFixSlice implements CustomSliceable {
            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
+15 −5
Original line number Diff line number Diff line
@@ -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<E> 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();
        SliceBackgroundWorker worker = getInstance(uri);
        if (worker == null) {
            final Class<? extends SliceBackgroundWorker> workerClass =
                    sliceable.getBackgroundWorkerClass();
        SliceBackgroundWorker worker = LIVE_WORKERS.get(uri);
        if (worker == null) {
            worker = createInstance(context, uri, workerClass);
            LIVE_WORKERS.put(uri, worker);
        }
+2 −2
Original line number Diff line number Diff line
@@ -105,8 +105,8 @@ public class WifiSlice implements CustomSliceable {
            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;