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

Commit a04de842 authored by Stefan Andonian's avatar Stefan Andonian
Browse files

Fix ConcurrentModificationExceptions during binding.

The same lists of extra items stored in BgModelData are also stored in
UI components. This is causing ConcurrentModificationExceptions. The
solution is to clone these lists or mark them as immutable before storing
them in their respective components.

Bug: 206918543
Test: Verified that crash no longer occurs after fix.
Change-Id: I571a2c451af58137aa7513b372b6a8ecf9bd3ff6
parent 698239e1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -305,7 +305,7 @@ public class HotseatPredictionController implements DragController.DragListener,
     * Sets or updates the predicted items only once the hotseat becomes hidden to the user
     */
    private void applyPredictedItems(FixedContainerItems items) {
        mPredictedItems = items.items;
        mPredictedItems = new ArrayList(items.items);
        if (mPredictedItems.isEmpty()) {
            HotseatRestoreHelper.restoreBackup(mLauncher);
        }
+6 −3
Original line number Diff line number Diff line
@@ -34,8 +34,10 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -68,7 +70,7 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
                        .map(info -> info.user)
                        .collect(Collectors.toSet());

        FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId);
        List<ItemInfo> items = new ArrayList<>(mTargets.size());
        for (AppTarget target : mTargets) {
            WorkspaceItemInfo itemInfo;
            ShortcutInfo si = target.getShortcutInfo();
@@ -107,10 +109,11 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
                }
            }

            itemInfo.container = fci.containerId;
            fci.items.add(itemInfo);
            itemInfo.container = mPredictorState.containerId;
            items.add(itemInfo);
        }

        FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId, items);
        dataModel.extraItems.put(fci.containerId, fci);
        bindExtraContainerItems(fci);
        usersForChangedShortcuts.forEach(
+2 −1
Original line number Diff line number Diff line
@@ -132,7 +132,8 @@ public class QuickstepModelDelegate extends ModelDelegate {

        // Widgets prediction isn't used frequently. And thus, it is not persisted on disk.
        mDataModel.extraItems.put(mWidgetsRecommendationState.containerId,
                new FixedContainerItems(mWidgetsRecommendationState.containerId));
                new FixedContainerItems(mWidgetsRecommendationState.containerId,
                        new ArrayList<>()));
        mActive = true;
    }

+6 −3
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import androidx.annotation.NonNull;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -91,10 +92,12 @@ public final class WidgetsPredictionUpdateTask extends BaseModelUpdateTask {
        if (servicePredictedItems.isEmpty()) {
            servicePredictedItems.addAll(localFilteredWidgets);
        }

        List<ItemInfo> items = servicePredictedItems.stream()
                .map(it -> new PendingAddWidgetInfo(it.widgetInfo, CONTAINER_WIDGETS_PREDICTION))
                .collect(Collectors.toList());
        FixedContainerItems fixedContainerItems =
                new FixedContainerItems(mPredictorState.containerId);
        servicePredictedItems.forEach(w -> fixedContainerItems.items.add(
                new PendingAddWidgetInfo(w.widgetInfo, CONTAINER_WIDGETS_PREDICTION)));
                new FixedContainerItems(mPredictorState.containerId, items);

        dataModel.extraItems.put(mPredictorState.containerId, fixedContainerItems);
        bindExtraContainerItems(fixedContainerItems);
+1 −2
Original line number Diff line number Diff line
@@ -118,8 +118,7 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask {
    }

    public void bindExtraContainerItems(@NonNull final FixedContainerItems item) {
        FixedContainerItems copy = item.clone();
        scheduleCallbackTask(c -> c.bindExtraContainerItems(copy));
        scheduleCallbackTask(c -> c.bindExtraContainerItems(item));
    }

    public void bindDeepShortcuts(@NonNull final BgDataModel dataModel) {
Loading