diff options
3 files changed, 98 insertions, 22 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index e80d3b3a6409..0fd244527540 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java @@ -36,11 +36,13 @@ import android.service.notification.Condition; import android.service.notification.IConditionListener; import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig.ZenRule; +import android.support.annotation.VisibleForTesting; import android.util.Log; import android.util.Slog; import com.android.systemui.qs.GlobalSetting; import com.android.systemui.settings.CurrentUserTracker; +import com.android.systemui.util.Utils; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -169,45 +171,32 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode } private void fireNextAlarmChanged() { - for (Callback cb : mCallbacks) { - cb.onNextAlarmChanged(); - } + Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged()); } private void fireEffectsSuppressorChanged() { - for (Callback cb : mCallbacks) { - cb.onEffectsSupressorChanged(); - } + Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged()); } private void fireZenChanged(int zen) { - for (Callback cb : mCallbacks) { - cb.onZenChanged(zen); - } + Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen)); } private void fireZenAvailableChanged(boolean available) { - for (Callback cb : mCallbacks) { - cb.onZenAvailableChanged(available); - } + Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available)); } private void fireConditionsChanged(Condition[] conditions) { - for (Callback cb : mCallbacks) { - cb.onConditionsChanged(conditions); - } + Utils.safeForeach(mCallbacks, c -> c.onConditionsChanged(conditions)); } private void fireManualRuleChanged(ZenRule rule) { - for (Callback cb : mCallbacks) { - cb.onManualRuleChanged(rule); - } + Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule)); } - private void fireConfigChanged(ZenModeConfig config) { - for (Callback cb : mCallbacks) { - cb.onConfigChanged(config); - } + @VisibleForTesting + protected void fireConfigChanged(ZenModeConfig config) { + Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config)); } private void updateConditions(Condition[] conditions) { diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java new file mode 100644 index 000000000000..f4aebae7bdaf --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui.util; + +import java.util.List; +import java.util.function.Consumer; + +public class Utils { + + /** + * Allows lambda iteration over a list. It is done in reverse order so it is safe + * to add or remove items during the iteration. + */ + public static <T> void safeForeach(List<T> list, Consumer<T> c) { + for (int i = list.size() - 1; i >= 0; i--) { + c.accept(list.get(i)); + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java new file mode 100644 index 000000000000..8124bf39328b --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.os.Handler; +import android.service.notification.ZenModeConfig; +import android.support.test.filters.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.policy.ZenModeController.Callback; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@RunWithLooper +public class ZenModeControllerImplTest extends SysuiTestCase { + + private Callback mCallback; + + @Test + public void testRemoveDuringCallback() { + ZenModeControllerImpl controller = new ZenModeControllerImpl(mContext, new Handler()); + mCallback = new Callback() { + @Override + public void onConfigChanged(ZenModeConfig config) { + controller.removeCallback(mCallback); + } + }; + controller.addCallback(mCallback); + Callback mockCallback = mock(Callback.class); + controller.addCallback(mockCallback); + controller.fireConfigChanged(null); + verify(mockCallback).onConfigChanged(eq(null)); + } + +}
\ No newline at end of file |