Loading src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java +5 −1 Original line number Diff line number Diff line Loading @@ -119,7 +119,7 @@ public class ScreenFlashNotificationColorDialogFragment extends DialogFragment i synchronized (this) { if (mTimer != null) mTimer.cancel(); mTimer = new Timer(); mTimer = createTimer(); if (mIsPreview) { mTimer.schedule(getStopTask(), 0); startDelay = BETWEEN_STOP_AND_START_DELAY_MS; Loading Loading @@ -176,4 +176,8 @@ public class ScreenFlashNotificationColorDialogFragment extends DialogFragment i getContext().sendBroadcast(stopIntent); mIsPreview = false; } Timer createTimer() { return new Timer(); } } tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java +80 −35 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentActivity; import com.android.settings.R; import com.android.settings.testutils.FakeTimer; import org.junit.Before; import org.junit.Test; Loading @@ -49,9 +50,12 @@ import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.shadows.ShadowContextWrapper; import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.function.Consumer; @RunWith(RobolectricTestRunner.class) public class ScreenFlashNotificationColorDialogFragmentTest { Loading @@ -68,9 +72,8 @@ public class ScreenFlashNotificationColorDialogFragmentTest { mShadowContextWrapper = shadowOf(fragmentActivity); mCurrentColor = ROSE.mColorInt; mDialogFragment = ScreenFlashNotificationColorDialogFragment.getInstance( mCurrentColor, selectedColor -> mCurrentColor = selectedColor ); mDialogFragment = createFragment(); mDialogFragment.show(fragmentActivity.getSupportFragmentManager(), "test"); mAlertDialog = (AlertDialog) mDialogFragment.getDialog(); Loading @@ -91,16 +94,19 @@ public class ScreenFlashNotificationColorDialogFragmentTest { } @Test public void clickNeutral_assertStartPreview() throws InterruptedException { public void clickNeutral_assertStartPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); Intent captured = getLastCapturedIntent(); assertThat(captured.getAction()).isEqualTo(ACTION_FLASH_NOTIFICATION_START_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_SHORT_PREVIEW)) .isEqualTo(TYPE_LONG_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR, Color.TRANSPARENT)) .isEqualTo(ROSE.mColorInt); assertStartPreview(ROSE.mColorInt); } @Test public void clickNeutral_flushAllScheduledTasks_assertStopPreview() { performClickOnDialog(BUTTON_NEUTRAL); getTimerFromFragment().runAllTasks(); assertStopPreview(); } @Test Loading @@ -116,51 +122,47 @@ public class ScreenFlashNotificationColorDialogFragmentTest { } @Test public void clickNeutralAndPause_assertStopPreview() throws InterruptedException { public void clickNeutralAndPause_assertStopPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); mDialogFragment.onPause(); Thread.sleep(100); assertThat(getLastCapturedIntent().getAction()) .isEqualTo(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW); assertStopPreview(); } @Test public void clickNeutralAndClickNegative_assertStopPreview() throws InterruptedException { public void clickNeutralAndClickNegative_assertStopPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); performClickOnDialog(BUTTON_NEGATIVE); Thread.sleep(100); assertThat(getLastCapturedIntent().getAction()) .isEqualTo(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW); assertStopPreview(); } @Test public void clickNeutralAndClickPositive_assertStopPreview() throws InterruptedException { public void clickNeutralAndClickPositive_assertStopPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); performClickOnDialog(BUTTON_POSITIVE); Thread.sleep(100); assertThat(getLastCapturedIntent().getAction()) .isEqualTo(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW); assertStopPreview(); } @Test public void clickNeutralAndClickColor_assertStartPreview() throws InterruptedException { public void clickNeutralAndClickColor_assertStartPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); checkColorButton(CYAN); Thread.sleep(500); // When changing the color while the preview is running, the fragment will schedule three // tasks: stop the current preview, start the new preview, stop the new preview int numOfPendingTasks = getTimerFromFragment().numOfPendingTasks(); // Run all the pending tasks except the last one while (numOfPendingTasks > 1) { getTimerFromFragment().runOneTask(); numOfPendingTasks--; } Intent captured = getLastCapturedIntent(); assertThat(captured.getAction()).isEqualTo(ACTION_FLASH_NOTIFICATION_START_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_SHORT_PREVIEW)) .isEqualTo(TYPE_LONG_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR, Color.TRANSPARENT)) .isEqualTo(CYAN.mColorInt); assertStartPreview(CYAN.mColorInt); } @Test Loading @@ -168,6 +170,7 @@ public class ScreenFlashNotificationColorDialogFragmentTest { checkColorButton(AZURE); performClickOnDialog(BUTTON_NEGATIVE); assertThat(getTimerFromFragment()).isNull(); assertThat(mCurrentColor).isEqualTo(ROSE.mColorInt); } Loading @@ -193,4 +196,46 @@ public class ScreenFlashNotificationColorDialogFragmentTest { final int size = capturedIntents.size(); return capturedIntents.get(size - 1); } private ScreenFlashNotificationColorDialogFragment createFragment() { ScreenFlashNotificationColorDialogFragmentWithFakeTimer fragment = new ScreenFlashNotificationColorDialogFragmentWithFakeTimer(); ReflectionHelpers.setField(fragment, "mCurrentColor", mCurrentColor); ReflectionHelpers.setField(fragment, "mConsumer", (Consumer<Integer>) selectedColor -> mCurrentColor = selectedColor); return fragment; } private FakeTimer getTimerFromFragment() { return (FakeTimer) ReflectionHelpers.getField(mDialogFragment, "mTimer"); } private void assertStartPreview(int color) { Intent captured = getLastCapturedIntent(); assertThat(captured.getAction()).isEqualTo(ACTION_FLASH_NOTIFICATION_START_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_SHORT_PREVIEW)) .isEqualTo(TYPE_LONG_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR, Color.TRANSPARENT)) .isEqualTo(color); } private void assertStopPreview() { assertThat(getTimerFromFragment().numOfPendingTasks()).isEqualTo(0); assertThat(getLastCapturedIntent().getAction()) .isEqualTo(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW); } /** * A {@link ScreenFlashNotificationColorDialogFragment} that uses a fake timer so that it won't * create unmanageable timer threads during test. */ public static class ScreenFlashNotificationColorDialogFragmentWithFakeTimer extends ScreenFlashNotificationColorDialogFragment { @Override Timer createTimer() { return new FakeTimer(); } } } tests/robotests/src/com/android/settings/testutils/FakeTimer.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.settings.testutils; import java.util.PriorityQueue; import java.util.Timer; import java.util.TimerTask; /** * A fake {@link Timer} that doesn't create a TimerThread which is hard to manage in test. */ public class FakeTimer extends Timer { private final PriorityQueue<ScheduledTimerTask> mQueue = new PriorityQueue<>(); public FakeTimer() { } @Override public void cancel() { mQueue.clear(); } @Override public void schedule(TimerTask task, long delay) { mQueue.offer(new ScheduledTimerTask(System.currentTimeMillis() + delay, task)); } /** * Runs the first task in the queue if there's any. */ public void runOneTask() { if (mQueue.size() > 0) { mQueue.poll().mTask.run(); } } /** * Runs all the queued tasks in order. */ public void runAllTasks() { while (mQueue.size() > 0) { mQueue.poll().mTask.run(); } } /** * Returns number of pending tasks in the timer */ public int numOfPendingTasks() { return mQueue.size(); } private static class ScheduledTimerTask implements Comparable<ScheduledTimerTask> { final long mTimeToRunInMillisSeconds; final TimerTask mTask; ScheduledTimerTask(long timeToRunInMilliSeconds, TimerTask task) { this.mTimeToRunInMillisSeconds = timeToRunInMilliSeconds; this.mTask = task; } @Override public int compareTo(ScheduledTimerTask other) { return Long.compare(this.mTimeToRunInMillisSeconds, other.mTimeToRunInMillisSeconds); } } } Loading
src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java +5 −1 Original line number Diff line number Diff line Loading @@ -119,7 +119,7 @@ public class ScreenFlashNotificationColorDialogFragment extends DialogFragment i synchronized (this) { if (mTimer != null) mTimer.cancel(); mTimer = new Timer(); mTimer = createTimer(); if (mIsPreview) { mTimer.schedule(getStopTask(), 0); startDelay = BETWEEN_STOP_AND_START_DELAY_MS; Loading Loading @@ -176,4 +176,8 @@ public class ScreenFlashNotificationColorDialogFragment extends DialogFragment i getContext().sendBroadcast(stopIntent); mIsPreview = false; } Timer createTimer() { return new Timer(); } }
tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java +80 −35 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentActivity; import com.android.settings.R; import com.android.settings.testutils.FakeTimer; import org.junit.Before; import org.junit.Test; Loading @@ -49,9 +50,12 @@ import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.shadows.ShadowContextWrapper; import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.function.Consumer; @RunWith(RobolectricTestRunner.class) public class ScreenFlashNotificationColorDialogFragmentTest { Loading @@ -68,9 +72,8 @@ public class ScreenFlashNotificationColorDialogFragmentTest { mShadowContextWrapper = shadowOf(fragmentActivity); mCurrentColor = ROSE.mColorInt; mDialogFragment = ScreenFlashNotificationColorDialogFragment.getInstance( mCurrentColor, selectedColor -> mCurrentColor = selectedColor ); mDialogFragment = createFragment(); mDialogFragment.show(fragmentActivity.getSupportFragmentManager(), "test"); mAlertDialog = (AlertDialog) mDialogFragment.getDialog(); Loading @@ -91,16 +94,19 @@ public class ScreenFlashNotificationColorDialogFragmentTest { } @Test public void clickNeutral_assertStartPreview() throws InterruptedException { public void clickNeutral_assertStartPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); Intent captured = getLastCapturedIntent(); assertThat(captured.getAction()).isEqualTo(ACTION_FLASH_NOTIFICATION_START_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_SHORT_PREVIEW)) .isEqualTo(TYPE_LONG_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR, Color.TRANSPARENT)) .isEqualTo(ROSE.mColorInt); assertStartPreview(ROSE.mColorInt); } @Test public void clickNeutral_flushAllScheduledTasks_assertStopPreview() { performClickOnDialog(BUTTON_NEUTRAL); getTimerFromFragment().runAllTasks(); assertStopPreview(); } @Test Loading @@ -116,51 +122,47 @@ public class ScreenFlashNotificationColorDialogFragmentTest { } @Test public void clickNeutralAndPause_assertStopPreview() throws InterruptedException { public void clickNeutralAndPause_assertStopPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); mDialogFragment.onPause(); Thread.sleep(100); assertThat(getLastCapturedIntent().getAction()) .isEqualTo(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW); assertStopPreview(); } @Test public void clickNeutralAndClickNegative_assertStopPreview() throws InterruptedException { public void clickNeutralAndClickNegative_assertStopPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); performClickOnDialog(BUTTON_NEGATIVE); Thread.sleep(100); assertThat(getLastCapturedIntent().getAction()) .isEqualTo(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW); assertStopPreview(); } @Test public void clickNeutralAndClickPositive_assertStopPreview() throws InterruptedException { public void clickNeutralAndClickPositive_assertStopPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); performClickOnDialog(BUTTON_POSITIVE); Thread.sleep(100); assertThat(getLastCapturedIntent().getAction()) .isEqualTo(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW); assertStopPreview(); } @Test public void clickNeutralAndClickColor_assertStartPreview() throws InterruptedException { public void clickNeutralAndClickColor_assertStartPreview() { performClickOnDialog(BUTTON_NEUTRAL); Thread.sleep(100); getTimerFromFragment().runOneTask(); checkColorButton(CYAN); Thread.sleep(500); // When changing the color while the preview is running, the fragment will schedule three // tasks: stop the current preview, start the new preview, stop the new preview int numOfPendingTasks = getTimerFromFragment().numOfPendingTasks(); // Run all the pending tasks except the last one while (numOfPendingTasks > 1) { getTimerFromFragment().runOneTask(); numOfPendingTasks--; } Intent captured = getLastCapturedIntent(); assertThat(captured.getAction()).isEqualTo(ACTION_FLASH_NOTIFICATION_START_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_SHORT_PREVIEW)) .isEqualTo(TYPE_LONG_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR, Color.TRANSPARENT)) .isEqualTo(CYAN.mColorInt); assertStartPreview(CYAN.mColorInt); } @Test Loading @@ -168,6 +170,7 @@ public class ScreenFlashNotificationColorDialogFragmentTest { checkColorButton(AZURE); performClickOnDialog(BUTTON_NEGATIVE); assertThat(getTimerFromFragment()).isNull(); assertThat(mCurrentColor).isEqualTo(ROSE.mColorInt); } Loading @@ -193,4 +196,46 @@ public class ScreenFlashNotificationColorDialogFragmentTest { final int size = capturedIntents.size(); return capturedIntents.get(size - 1); } private ScreenFlashNotificationColorDialogFragment createFragment() { ScreenFlashNotificationColorDialogFragmentWithFakeTimer fragment = new ScreenFlashNotificationColorDialogFragmentWithFakeTimer(); ReflectionHelpers.setField(fragment, "mCurrentColor", mCurrentColor); ReflectionHelpers.setField(fragment, "mConsumer", (Consumer<Integer>) selectedColor -> mCurrentColor = selectedColor); return fragment; } private FakeTimer getTimerFromFragment() { return (FakeTimer) ReflectionHelpers.getField(mDialogFragment, "mTimer"); } private void assertStartPreview(int color) { Intent captured = getLastCapturedIntent(); assertThat(captured.getAction()).isEqualTo(ACTION_FLASH_NOTIFICATION_START_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_SHORT_PREVIEW)) .isEqualTo(TYPE_LONG_PREVIEW); assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR, Color.TRANSPARENT)) .isEqualTo(color); } private void assertStopPreview() { assertThat(getTimerFromFragment().numOfPendingTasks()).isEqualTo(0); assertThat(getLastCapturedIntent().getAction()) .isEqualTo(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW); } /** * A {@link ScreenFlashNotificationColorDialogFragment} that uses a fake timer so that it won't * create unmanageable timer threads during test. */ public static class ScreenFlashNotificationColorDialogFragmentWithFakeTimer extends ScreenFlashNotificationColorDialogFragment { @Override Timer createTimer() { return new FakeTimer(); } } }
tests/robotests/src/com/android/settings/testutils/FakeTimer.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.settings.testutils; import java.util.PriorityQueue; import java.util.Timer; import java.util.TimerTask; /** * A fake {@link Timer} that doesn't create a TimerThread which is hard to manage in test. */ public class FakeTimer extends Timer { private final PriorityQueue<ScheduledTimerTask> mQueue = new PriorityQueue<>(); public FakeTimer() { } @Override public void cancel() { mQueue.clear(); } @Override public void schedule(TimerTask task, long delay) { mQueue.offer(new ScheduledTimerTask(System.currentTimeMillis() + delay, task)); } /** * Runs the first task in the queue if there's any. */ public void runOneTask() { if (mQueue.size() > 0) { mQueue.poll().mTask.run(); } } /** * Runs all the queued tasks in order. */ public void runAllTasks() { while (mQueue.size() > 0) { mQueue.poll().mTask.run(); } } /** * Returns number of pending tasks in the timer */ public int numOfPendingTasks() { return mQueue.size(); } private static class ScheduledTimerTask implements Comparable<ScheduledTimerTask> { final long mTimeToRunInMillisSeconds; final TimerTask mTask; ScheduledTimerTask(long timeToRunInMilliSeconds, TimerTask task) { this.mTimeToRunInMillisSeconds = timeToRunInMilliSeconds; this.mTask = task; } @Override public int compareTo(ScheduledTimerTask other) { return Long.compare(this.mTimeToRunInMillisSeconds, other.mTimeToRunInMillisSeconds); } } }