Merge "Fix flaky VibratorServiceTest" into sc-dev

This commit is contained in:
Michael Wright
2021-02-09 03:04:42 +00:00
committed by Android (Google) Code Review
2 changed files with 42 additions and 61 deletions

View File

@@ -50,6 +50,7 @@ import android.os.Looper;
import android.os.PowerManagerInternal; import android.os.PowerManagerInternal;
import android.os.PowerSaveState; import android.os.PowerSaveState;
import android.os.Process; import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.VibrationAttributes; import android.os.VibrationAttributes;
import android.os.VibrationEffect; import android.os.VibrationEffect;
@@ -81,6 +82,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@@ -92,6 +94,7 @@ import java.util.stream.Collectors;
@Presubmit @Presubmit
public class VibratorServiceTest { public class VibratorServiceTest {
private static final int TEST_TIMEOUT_MILLIS = 1_000;
private static final int UID = Process.ROOT_UID; private static final int UID = Process.ROOT_UID;
private static final int VIBRATOR_ID = 1; private static final int VIBRATOR_ID = 1;
private static final String PACKAGE_NAME = "package"; private static final String PACKAGE_NAME = "package";
@@ -342,8 +345,8 @@ public class VibratorServiceTest {
verify(mIInputManagerMock).vibrate(eq(1), eq(effect), any()); verify(mIInputManagerMock).vibrate(eq(1), eq(effect), any());
// VibrationThread will start this vibration async, so wait before checking it never played. // VibrationThread will start this vibration async, so wait before checking it never played.
Thread.sleep(10); assertFalse(waitUntil(s -> !mVibratorProvider.getEffects().isEmpty(), service,
assertTrue(mVibratorProvider.getEffects().isEmpty()); /* timeout= */ 20));
} }
@Test @Test
@@ -399,8 +402,8 @@ public class VibratorServiceTest {
verify(mIInputManagerMock).vibrate(eq(1), any(), any()); verify(mIInputManagerMock).vibrate(eq(1), any(), any());
// VibrationThread will start this vibration async, so wait before checking it never played. // VibrationThread will start this vibration async, so wait before checking it never played.
Thread.sleep(10); assertFalse(waitUntil(s -> !mVibratorProvider.getEffects().isEmpty(), service,
assertTrue(mVibratorProvider.getEffects().isEmpty()); /* timeout= */ 20));
} }
@Test @Test
@@ -409,16 +412,10 @@ public class VibratorServiceTest {
mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
vibrate(service, VibrationEffect.createOneShot(1000, 100), HAPTIC_FEEDBACK_ATTRS); vibrate(service, VibrationEffect.createOneShot(1000, 100), HAPTIC_FEEDBACK_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// VibrationThread will start this vibration async, so wait before triggering callbacks.
Thread.sleep(10);
assertTrue(service.isVibrating());
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
assertTrue(waitUntil(s -> !s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// Wait for callback to cancel vibration.
Thread.sleep(10);
assertFalse(service.isVibrating());
} }
@Test @Test
@@ -427,26 +424,18 @@ public class VibratorServiceTest {
mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
vibrate(service, VibrationEffect.createOneShot(1000, 100), RINGTONE_ATTRS); vibrate(service, VibrationEffect.createOneShot(1000, 100), RINGTONE_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// VibrationThread will start this vibration async, so wait before triggering callbacks.
Thread.sleep(10);
assertTrue(service.isVibrating());
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
// Settings callback is async, so wait before checking it never got cancelled.
// Wait for callback to cancel vibration. assertFalse(waitUntil(s -> !s.isVibrating(), service, /* timeout= */ 20));
Thread.sleep(10);
assertTrue(service.isVibrating());
} }
@Test @Test
public void vibrate_withSettingsChanged_doNotCancelVibration() throws Exception { public void vibrate_withSettingsChanged_doNotCancelVibration() throws Exception {
VibratorService service = createService(); VibratorService service = createService();
vibrate(service, VibrationEffect.createOneShot(1000, 100), HAPTIC_FEEDBACK_ATTRS); vibrate(service, VibrationEffect.createOneShot(1000, 100), HAPTIC_FEEDBACK_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// VibrationThread will start this vibration async, so wait before triggering callbacks.
Thread.sleep(10);
assertTrue(service.isVibrating());
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
Vibrator.VIBRATION_INTENSITY_MEDIUM); Vibrator.VIBRATION_INTENSITY_MEDIUM);
@@ -454,9 +443,8 @@ public class VibratorServiceTest {
// FakeSettingsProvider don't support testing triggering ContentObserver yet. // FakeSettingsProvider don't support testing triggering ContentObserver yet.
service.updateVibrators(); service.updateVibrators();
// Wait for callback to cancel vibration. // Settings callback is async, so wait before checking it never got cancelled.
Thread.sleep(10); assertFalse(waitUntil(s -> !s.isVibrating(), service, /* timeout= */ 20));
assertTrue(service.isVibrating());
} }
@Test @Test
@@ -488,8 +476,8 @@ public class VibratorServiceTest {
inOrderVerifier.verify(mIInputManagerMock).vibrate(eq(2), eq(effect), any()); inOrderVerifier.verify(mIInputManagerMock).vibrate(eq(2), eq(effect), any());
// VibrationThread will start this vibration async, so wait before checking it never played. // VibrationThread will start this vibration async, so wait before checking it never played.
Thread.sleep(10); assertFalse(waitUntil(s -> !mVibratorProvider.getEffects().isEmpty(), service,
assertTrue(mVibratorProvider.getEffects().isEmpty()); /* timeout= */ 20));
} }
@Test @Test
@@ -521,8 +509,8 @@ public class VibratorServiceTest {
verify(mIInputManagerMock).vibrate(eq(1), eq(effect), any()); verify(mIInputManagerMock).vibrate(eq(1), eq(effect), any());
// VibrationThread will start this vibration async, so wait before checking it never played. // VibrationThread will start this vibration async, so wait before checking it never played.
Thread.sleep(10); assertFalse(waitUntil(s -> !mVibratorProvider.getEffects().isEmpty(), service,
assertTrue(mVibratorProvider.getEffects().isEmpty()); /* timeout= */ 20));
} }
@Test @Test
@@ -531,18 +519,12 @@ public class VibratorServiceTest {
VibratorService service = createService(); VibratorService service = createService();
vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS); vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// VibrationThread will start this vibration async, so wait before triggering callbacks.
Thread.sleep(10);
assertTrue(service.isVibrating());
// Trigger callbacks from controller. // Trigger callbacks from controller.
mTestLooper.moveTimeForward(50); mTestLooper.moveTimeForward(50);
mTestLooper.dispatchAll(); mTestLooper.dispatchAll();
assertTrue(waitUntil(s -> !s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// VibrationThread needs some time to react to native callbacks and stop the vibrator.
Thread.sleep(10);
assertFalse(service.isVibrating());
} }
@Test @Test
@@ -550,16 +532,10 @@ public class VibratorServiceTest {
VibratorService service = createService(); VibratorService service = createService();
vibrate(service, VibrationEffect.createOneShot(100, 100), ALARM_ATTRS); vibrate(service, VibrationEffect.createOneShot(100, 100), ALARM_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// VibrationThread will start this vibration async, so wait before checking.
Thread.sleep(10);
assertTrue(service.isVibrating());
service.cancelVibrate(service); service.cancelVibrate(service);
assertTrue(waitUntil(s -> !s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// VibrationThread will stop this vibration async, so wait before checking.
Thread.sleep(10);
assertFalse(service.isVibrating());
} }
@Test @Test
@@ -584,17 +560,13 @@ public class VibratorServiceTest {
service.registerVibratorStateListener(mVibratorStateListenerMock); service.registerVibratorStateListener(mVibratorStateListenerMock);
vibrate(service, VibrationEffect.createOneShot(30, 100), ALARM_ATTRS); vibrate(service, VibrationEffect.createOneShot(30, 100), ALARM_ATTRS);
assertTrue(waitUntil(s -> s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
// VibrationThread will start this vibration async, so wait before triggering callbacks.
Thread.sleep(10);
assertTrue(service.isVibrating());
service.unregisterVibratorStateListener(mVibratorStateListenerMock); service.unregisterVibratorStateListener(mVibratorStateListenerMock);
// Trigger callbacks from controller. // Trigger callbacks from controller.
mTestLooper.moveTimeForward(50); mTestLooper.moveTimeForward(50);
mTestLooper.dispatchAll(); mTestLooper.dispatchAll();
Thread.sleep(20); assertTrue(waitUntil(s -> !s.isVibrating(), service, TEST_TIMEOUT_MILLIS));
assertFalse(service.isVibrating());
InOrder inOrderVerifier = inOrder(mVibratorStateListenerMock); InOrder inOrderVerifier = inOrder(mVibratorStateListenerMock);
// First notification done when listener is registered. // First notification done when listener is registered.
@@ -771,4 +743,15 @@ public class VibratorServiceTest {
private void setGlobalSetting(String settingName, int value) { private void setGlobalSetting(String settingName, int value) {
Settings.Global.putInt(mContextSpy.getContentResolver(), settingName, value); Settings.Global.putInt(mContextSpy.getContentResolver(), settingName, value);
} }
private boolean waitUntil(Predicate<VibratorService> predicate,
VibratorService service, long timeout) throws InterruptedException {
long timeoutTimestamp = SystemClock.uptimeMillis() + timeout;
boolean predicateResult = false;
while (!predicateResult && SystemClock.uptimeMillis() < timeoutTimestamp) {
Thread.sleep(10);
predicateResult = predicate.test(service);
}
return predicateResult;
}
} }

View File

@@ -229,9 +229,9 @@ public class VibrationThreadTest {
.compose(); .compose();
VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect); VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect);
Thread.sleep(20); assertTrue(waitUntil(t -> t.getVibrators().get(VIBRATOR_ID).isVibrating(), vibrationThread,
TEST_TIMEOUT_MILLIS));
assertTrue(vibrationThread.isAlive()); assertTrue(vibrationThread.isAlive());
assertTrue(vibrationThread.getVibrators().get(VIBRATOR_ID).isVibrating());
// Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should // Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately. // fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.
@@ -254,9 +254,9 @@ public class VibrationThreadTest {
VibrationEffect effect = VibrationEffect.createWaveform(new long[]{100}, new int[]{100}, 0); VibrationEffect effect = VibrationEffect.createWaveform(new long[]{100}, new int[]{100}, 0);
VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect); VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect);
Thread.sleep(20); assertTrue(waitUntil(t -> t.getVibrators().get(VIBRATOR_ID).isVibrating(), vibrationThread,
TEST_TIMEOUT_MILLIS));
assertTrue(vibrationThread.isAlive()); assertTrue(vibrationThread.isAlive());
assertTrue(vibrationThread.getVibrators().get(VIBRATOR_ID).isVibrating());
// Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should // Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately. // fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.
@@ -621,10 +621,8 @@ public class VibrationThreadTest {
.combine(); .combine();
VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect); VibrationThread vibrationThread = startThreadAndDispatcher(vibrationId, effect);
Thread.sleep(10); assertTrue(waitUntil(t -> t.getVibrators().get(2).isVibrating(), vibrationThread,
assertTrue(vibrationThread.isAlive()); TEST_TIMEOUT_MILLIS));
assertTrue(vibrationThread.getVibrators().get(1).isVibrating());
assertTrue(vibrationThread.getVibrators().get(2).isVibrating());
// Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should // Run cancel in a separate thread so if VibrationThread.cancel blocks then this test should
// fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately. // fail at waitForCompletion(vibrationThread) if the vibration not cancelled immediately.