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

Commit c6f61ee9 authored by Steve Elliott's avatar Steve Elliott
Browse files

Defensively copy callback collections before invoking

This is done in order to prevent ConcurrentModificationExceptions,
caused by the callback unregistering itself when invoked. The pattern
used by this CL is also used by StatusBarStateControllerImpl.

Fixes: 192192372
Test: manual
Change-Id: Ibac2282d5c9242ae063adb2247d4297291fa3abf
Merged-In: Ibac2282d5c9242ae063adb2247d4297291fa3abf
parent a40b1cb4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ public class KeyguardBouncer {
    private final Runnable mResetRunnable = ()-> {
        if (mKeyguardViewController != null) {
            mKeyguardViewController.resetSecurityContainer();
            for (KeyguardResetCallback callback : mResetCallbacks) {
            for (KeyguardResetCallback callback : new ArrayList<>(mResetCallbacks)) {
                callback.onKeyguardReset();
            }
        }
+14 −10
Original line number Diff line number Diff line
@@ -55,16 +55,18 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.KeyguardStateController;

import com.google.android.collect.Lists;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import javax.inject.Inject;

@@ -100,7 +102,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
    private ForcePluginOpenListener mForcePluginOpenListener;
    private Consumer<Integer> mScrimsVisibilityListener;
    private final ArrayList<WeakReference<StatusBarWindowCallback>>
            mCallbacks = Lists.newArrayList();
            mCallbacks = new ArrayList<>();

    private final SysuiColorExtractor mColorExtractor;
    private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@@ -464,15 +466,17 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW

    @Override
    public void notifyStateChangedCallbacks() {
        for (int i = 0; i < mCallbacks.size(); i++) {
            StatusBarWindowCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
        // Copy callbacks to separate ArrayList to avoid concurrent modification
        List<StatusBarWindowCallback> activeCallbacks = mCallbacks.stream()
                .map(Reference::get)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        for (StatusBarWindowCallback cb : activeCallbacks) {
            cb.onStateChanged(mCurrentState.mKeyguardShowing,
                    mCurrentState.mKeyguardOccluded,
                    mCurrentState.mBouncerShowing);
        }
    }
    }

    private void applyModalFlag(State state) {
        if (state.mHeadsUpShowing) {
+5 −4
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;

/**
@@ -157,7 +158,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
                        NotificationPeekEvent.NOTIFICATION_PEEK, entry.getSbn().getUid(),
                        entry.getSbn().getPackageName(), entry.getSbn().getInstanceId());
            }
            for (OnHeadsUpChangedListener listener : mListeners) {
            for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
                if (isPinned) {
                    listener.onHeadsUpPinned(entry);
                } else {
@@ -177,7 +178,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
        entry.setHeadsUp(true);
        setEntryPinned((HeadsUpEntry) alertEntry, shouldHeadsUpBecomePinned(entry));
        EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 1 /* visible */);
        for (OnHeadsUpChangedListener listener : mListeners) {
        for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
            listener.onHeadsUpStateChanged(entry, true);
        }
    }
@@ -188,7 +189,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
        entry.setHeadsUp(false);
        setEntryPinned((HeadsUpEntry) alertEntry, false /* isPinned */);
        EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 0 /* visible */);
        for (OnHeadsUpChangedListener listener : mListeners) {
        for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
            listener.onHeadsUpStateChanged(entry, false);
        }
    }
@@ -206,7 +207,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
        if (mHasPinnedNotification) {
            MetricsLogger.count(mContext, "note_peek", 1);
        }
        for (OnHeadsUpChangedListener listener : mListeners) {
        for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
            listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
        }
    }
+1 −1
Original line number Diff line number Diff line
@@ -807,7 +807,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    }

    private void onEditTextFocusChanged(RemoteEditText remoteEditText, boolean focused) {
        for (View.OnFocusChangeListener listener : mEditTextFocusChangeListeners) {
        for (View.OnFocusChangeListener listener : new ArrayList<>(mEditTextFocusChangeListeners)) {
            listener.onFocusChange(remoteEditText, focused);
        }
    }