[CEC Configuration] Fix race condition with listeners

Bug: 178095692
Test: atest HdmiCecConfigTest --iterations 25
Change-Id: I5ac00d596fe3d4b5af5f69d2fbaac9cc38f99ca1
This commit is contained in:
Michal Olech
2021-01-22 15:42:33 +01:00
parent b695454d8a
commit b4e2a5bc6d

View File

@@ -37,6 +37,7 @@ import android.provider.Settings.Global;
import android.util.ArrayMap;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.hdmi.cec.config.CecSettings;
import com.android.server.hdmi.cec.config.Setting;
@@ -95,6 +96,9 @@ public class HdmiCecConfig {
@Nullable private final CecSettings mSystemConfig;
@Nullable private final CecSettings mVendorOverride;
private final Object mLock = new Object();
@GuardedBy("mLock")
private final ArrayMap<Setting, Set<SettingChangeListener>>
mSettingChangeListeners = new ArrayMap<>();
@@ -389,12 +393,14 @@ public class HdmiCecConfig {
}
private void notifySettingChanged(@NonNull Setting setting) {
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
if (listeners == null) {
return; // No listeners registered, do nothing.
}
for (SettingChangeListener listener: listeners) {
listener.onChange(setting.getName());
synchronized (mLock) {
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
if (listeners == null) {
return; // No listeners registered, do nothing.
}
for (SettingChangeListener listener: listeners) {
listener.onChange(setting.getName());
}
}
}
@@ -440,10 +446,12 @@ public class HdmiCecConfig {
throw new IllegalArgumentException("Change listeners for setting '" + name
+ "' not supported.");
}
if (!mSettingChangeListeners.containsKey(setting)) {
mSettingChangeListeners.put(setting, new HashSet<>());
synchronized (mLock) {
if (!mSettingChangeListeners.containsKey(setting)) {
mSettingChangeListeners.put(setting, new HashSet<>());
}
mSettingChangeListeners.get(setting).add(listener);
}
mSettingChangeListeners.get(setting).add(listener);
}
/**
@@ -455,11 +463,13 @@ public class HdmiCecConfig {
if (setting == null) {
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
}
if (mSettingChangeListeners.containsKey(setting)) {
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
listeners.remove(listener);
if (listeners.isEmpty()) {
mSettingChangeListeners.remove(setting);
synchronized (mLock) {
if (mSettingChangeListeners.containsKey(setting)) {
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
listeners.remove(listener);
if (listeners.isEmpty()) {
mSettingChangeListeners.remove(setting);
}
}
}
}