diff options
4 files changed, 163 insertions, 126 deletions
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java index 417fbd06be66..0d5bf95d959d 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java @@ -67,6 +67,7 @@ public class VibratorControlServiceTest { @Mock private PackageManagerInternal mPackageManagerInternalMock; + private TestLooper mTestLooper; private FakeVibratorController mFakeVibratorController; private VibratorControlService mVibratorControlService; private VibrationSettings mVibrationSettings; @@ -74,6 +75,7 @@ public class VibratorControlServiceTest { @Before public void setUp() throws Exception { + mTestLooper = new TestLooper(); when(mPackageManagerInternalMock.getSystemUiServiceComponent()) .thenReturn(new ComponentName("", "")); LocalServices.removeServiceForTest(PackageManagerInternal.class); @@ -83,7 +85,7 @@ public class VibratorControlServiceTest { mVibrationSettings = new VibrationSettings( ApplicationProvider.getApplicationContext(), new Handler(testLooper.getLooper())); - mFakeVibratorController = new FakeVibratorController(); + mFakeVibratorController = new FakeVibratorController(mTestLooper.getLooper()); mVibratorControlService = new VibratorControlService(new VibratorControllerHolder(), mMockVibrationScaler, mVibrationSettings, mLock); } @@ -108,13 +110,13 @@ public class VibratorControlServiceTest { @Test public void testUnregisterVibratorController_providingAnInvalidController_ignoresRequest() throws RemoteException { - FakeVibratorController fakeController1 = new FakeVibratorController(); - FakeVibratorController fakeController2 = new FakeVibratorController(); - mVibratorControlService.registerVibratorController(fakeController1); - mVibratorControlService.unregisterVibratorController(fakeController2); + FakeVibratorController controller1 = new FakeVibratorController(mTestLooper.getLooper()); + FakeVibratorController controller2 = new FakeVibratorController(mTestLooper.getLooper()); + mVibratorControlService.registerVibratorController(controller1); + mVibratorControlService.unregisterVibratorController(controller2); verifyZeroInteractions(mMockVibrationScaler); - assertThat(fakeController1.isLinkedToDeath).isTrue(); + assertThat(controller1.isLinkedToDeath).isTrue(); } @Test diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerHolderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerHolderTest.java index 79abe21a301d..db823d649cb6 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerHolderTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerHolderTest.java @@ -18,23 +18,26 @@ package com.android.server.vibrator; import static com.google.common.truth.Truth.assertThat; -import android.os.RemoteException; +import android.os.test.TestLooper; import org.junit.Before; import org.junit.Test; public class VibratorControllerHolderTest { - private final FakeVibratorController mFakeVibratorController = new FakeVibratorController(); + private TestLooper mTestLooper; + private FakeVibratorController mFakeVibratorController; private VibratorControllerHolder mVibratorControllerHolder; @Before public void setUp() throws Exception { + mTestLooper = new TestLooper(); + mFakeVibratorController = new FakeVibratorController(mTestLooper.getLooper()); mVibratorControllerHolder = new VibratorControllerHolder(); } @Test - public void testSetVibratorController_linksVibratorControllerToDeath() throws RemoteException { + public void testSetVibratorController_linksVibratorControllerToDeath() { mVibratorControllerHolder.setVibratorController(mFakeVibratorController); assertThat(mVibratorControllerHolder.getVibratorController()) .isEqualTo(mFakeVibratorController); @@ -42,8 +45,7 @@ public class VibratorControllerHolderTest { } @Test - public void testSetVibratorController_setControllerToNull_unlinksVibratorControllerToDeath() - throws RemoteException { + public void testSetVibratorController_setControllerToNull_unlinksVibratorControllerToDeath() { mVibratorControllerHolder.setVibratorController(mFakeVibratorController); mVibratorControllerHolder.setVibratorController(null); assertThat(mFakeVibratorController.isLinkedToDeath).isFalse(); @@ -51,8 +53,7 @@ public class VibratorControllerHolderTest { } @Test - public void testBinderDied_withValidController_unlinksVibratorControllerToDeath() - throws RemoteException { + public void testBinderDied_withValidController_unlinksVibratorControllerToDeath() { mVibratorControllerHolder.setVibratorController(mFakeVibratorController); mVibratorControllerHolder.binderDied(mFakeVibratorController); assertThat(mFakeVibratorController.isLinkedToDeath).isFalse(); @@ -60,10 +61,10 @@ public class VibratorControllerHolderTest { } @Test - public void testBinderDied_withInvalidController_ignoresRequest() - throws RemoteException { + public void testBinderDied_withInvalidController_ignoresRequest() { mVibratorControllerHolder.setVibratorController(mFakeVibratorController); - FakeVibratorController imposterVibratorController = new FakeVibratorController(); + FakeVibratorController imposterVibratorController = + new FakeVibratorController(mTestLooper.getLooper()); mVibratorControllerHolder.binderDied(imposterVibratorController); assertThat(mFakeVibratorController.isLinkedToDeath).isTrue(); assertThat(mVibratorControllerHolder.getVibratorController()) diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java index ed89ccf07453..d2ad61f2ba9f 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -97,7 +97,6 @@ import android.view.InputDevice; import android.view.flags.Flags; import androidx.test.InstrumentationRegistry; -import androidx.test.filters.FlakyTest; import com.android.internal.app.IBatteryStats; import com.android.internal.util.FrameworkStatsLog; @@ -117,6 +116,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.time.Duration; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -128,9 +128,7 @@ import java.util.function.Predicate; public class VibratorManagerServiceTest { private static final int TEST_TIMEOUT_MILLIS = 1_000; - // Time to allow for a cancellation to complete (notably including system ramp down), but not so - // long that tests easily get really slow or flaky. If a vibration is close to this, it should - // be cancelled in the body of the individual test. + // Time to allow for a cancellation to complete and the vibrators to become idle. private static final int CLEANUP_TIMEOUT_MILLIS = 100; private static final int UID = Process.ROOT_UID; private static final int VIRTUAL_DEVICE_ID = 1; @@ -186,8 +184,8 @@ public class VibratorManagerServiceTest { private AudioManager mAudioManagerMock; private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>(); - - private SparseArray<VibrationEffect> mHapticFeedbackVibrationMap = new SparseArray<>(); + private final SparseArray<VibrationEffect> mHapticFeedbackVibrationMap = new SparseArray<>(); + private final List<HalVibration> mPendingVibrations = new ArrayList<>(); private VibratorManagerService mService; private Context mContextSpy; @@ -207,7 +205,7 @@ public class VibratorManagerServiceTest { mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mIInputManagerMock); mVibrationConfig = new VibrationConfig(mContextSpy.getResources()); - mFakeVibratorController = new FakeVibratorController(); + mFakeVibratorController = new FakeVibratorController(mTestLooper.getLooper()); ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy); when(mContextSpy.getContentResolver()).thenReturn(contentResolver); @@ -253,12 +251,15 @@ public class VibratorManagerServiceTest { @After public void tearDown() throws Exception { if (mService != null) { - // Wait until all vibrators have stopped vibrating, with a bit of flexibility for tests - // that just do a click or have cancelled at the end (waiting for ramp-down). - // - // Note: if a test is flaky here, check whether a VibrationEffect duration is close to - // CLEANUP_TIMEOUT_MILLIS - in which case it's probably best to just cancel that effect - // explicitly at the end of the test case (rather than letting it run and race flakily). + if (!mPendingVibrations.stream().allMatch(HalVibration::hasEnded)) { + // Cancel any pending vibration from tests. + cancelVibrate(mService); + for (HalVibration vibration : mPendingVibrations) { + vibration.waitForEnd(); + } + } + // Wait until all vibrators have stopped vibrating, waiting for ramp-down. + // Note: if a test is flaky here something is wrong with the vibration finalization. assertTrue(waitUntil(s -> { for (int vibratorId : mService.getVibratorIds()) { if (s.isVibrating(vibratorId)) { @@ -266,7 +267,7 @@ public class VibratorManagerServiceTest { } } return true; - }, mService, CLEANUP_TIMEOUT_MILLIS)); + }, mService, mVibrationConfig.getRampDownDurationMs() + CLEANUP_TIMEOUT_MILLIS)); } LocalServices.removeServiceForTest(PackageManagerInternal.class); @@ -323,21 +324,26 @@ public class VibratorManagerServiceTest { (VibratorManagerService.ExternalVibratorService) service; } else if (service instanceof VibratorControlService) { mVibratorControlService = (VibratorControlService) service; + mFakeVibratorController.setVibratorControlService( + mVibratorControlService); } } + @Override HapticFeedbackVibrationProvider createHapticFeedbackVibrationProvider( Resources resources, VibratorInfo vibratorInfo) { return new HapticFeedbackVibrationProvider( resources, vibratorInfo, mHapticFeedbackVibrationMap); } + @Override VibratorControllerHolder createVibratorControllerHolder() { VibratorControllerHolder holder = new VibratorControllerHolder(); holder.setVibratorController(mFakeVibratorController); return holder; } + @Override boolean isServiceDeclared(String name) { return true; } @@ -486,8 +492,9 @@ public class VibratorManagerServiceTest { InOrder inOrderVerifier = inOrder(listenerMock); // First notification done when listener is registered. inOrderVerifier.verify(listenerMock).onVibrating(eq(false)); + // Vibrator on notification done before vibration ended, no need to wait. inOrderVerifier.verify(listenerMock).onVibrating(eq(true)); - // The last notification is after the vibration has completed. + // Vibrator off notification done after vibration completed, wait for notification. inOrderVerifier.verify(listenerMock, timeout(TEST_TIMEOUT_MILLIS)).onVibrating(eq(false)); inOrderVerifier.verifyNoMoreInteractions(); @@ -517,6 +524,7 @@ public class VibratorManagerServiceTest { InOrder inOrderVerifier = inOrder(listenerMock); // First notification done when listener is registered. inOrderVerifier.verify(listenerMock).onVibrating(eq(false)); + // Vibrator on notification done before vibration ended, no need to wait. inOrderVerifier.verify(listenerMock).onVibrating(eq(true)); inOrderVerifier.verify(listenerMock, atLeastOnce()).asBinder(); // unregister inOrderVerifier.verifyNoMoreInteractions(); @@ -541,7 +549,6 @@ public class VibratorManagerServiceTest { verify(listeners[0]).onVibrating(eq(true)); verify(listeners[1]).onVibrating(eq(true)); verify(listeners[2], never()).onVibrating(eq(true)); - cancelVibrate(service); // Clean up long-ish effect. } @Test @@ -889,21 +896,24 @@ public class VibratorManagerServiceTest { eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString()); } - @FlakyTest @Test public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); - vibrate(service, repeatingEffect, new VibrationAttributes.Builder().setUsage( - VibrationAttributes.USAGE_UNKNOWN).build()); + new long[]{10, 10_000}, new int[]{128, 255}, 1); + vibrate(service, repeatingEffect, + new VibrationAttributes.Builder() + .setUsage(VibrationAttributes.USAGE_UNKNOWN) + .build()); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), HAPTIC_FEEDBACK_ATTRS); @@ -914,9 +924,8 @@ public class VibratorManagerServiceTest { // The second vibration shouldn't have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // No segment played is the prebaked CLICK from the second vibration. - assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream() + assertFalse(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); - cancelVibrate(service); // Clean up repeating effect. } @Test @@ -930,11 +939,13 @@ public class VibratorManagerServiceTest { VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10, 10_000}, new int[]{255, 0}, 1); + new long[]{10, 10_000}, new int[]{128, 255}, 1); vibrate(service, repeatingEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until the off waveform step. - assertTrue(waitUntil(s -> fakeVibrator.getOffCount() > 0, service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); // Cancel vibration right before requesting a new one. // This should trigger slow IVibrator.off before setting the vibration status to cancelled. @@ -942,6 +953,8 @@ public class VibratorManagerServiceTest { vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS); + // The second vibration should have recorded that the vibrators were turned on. + verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); // Check that second vibration was played. assertTrue(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); @@ -951,45 +964,47 @@ public class VibratorManagerServiceTest { public void vibrate_withNewSameImportanceVibrationAndBothRepeating_cancelsOngoingEffect() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + new long[]{10, 10_000}, new int[]{128, 255}, 1); vibrate(service, repeatingEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); VibrationEffect repeatingEffect2 = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + new long[]{10, 10_000}, new int[]{255, 128}, 1); vibrate(service, repeatingEffect2, ALARM_ATTRS); - // VibrationThread will start this vibration async, so wait before checking it started. - assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() == 2, - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 4, service, + TEST_TIMEOUT_MILLIS)); // The second vibration should have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); - - cancelVibrate(service); // Clean up repeating effect. } - @FlakyTest @Test public void vibrate_withNewSameImportanceVibrationButOngoingIsRepeating_ignoreNewVibration() throws Exception { mockVibrators(1); FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10, 10_000}, new int[]{255, 0}, 1); + new long[]{10, 10_000}, new int[]{128, 255}, 1); vibrate(service, repeatingEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !fakeVibrator.getAllEffectSegments().isEmpty(), service, + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), @@ -998,53 +1013,55 @@ public class VibratorManagerServiceTest { // The second vibration shouldn't have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // The second vibration shouldn't have played any prebaked segment. - assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream() + assertFalse(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); - cancelVibrate(service); // Clean up long effect. } @Test public void vibrate_withNewUnknownUsageVibrationAndRepeating_cancelsOngoingEffect() throws Exception { mockVibrators(1); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect repeatingEffect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + new long[]{10, 10_000}, new int[]{128, 255}, 1); vibrate(service, repeatingEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); VibrationEffect repeatingEffect2 = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + new long[]{10, 10_000}, new int[]{255, 128}, 1); vibrate(service, repeatingEffect2, UNKNOWN_ATTRS); - // VibrationThread will start this vibration async, so wait before checking it started. - assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() == 2, - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 4, service, + TEST_TIMEOUT_MILLIS)); // The second vibration should have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); - - cancelVibrate(service); // Clean up repeating effect. } - @FlakyTest @Test public void vibrate_withNewUnknownUsageVibrationAndNotRepeating_ignoreNewVibration() throws Exception { mockVibrators(1); FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect alarmEffect = VibrationEffect.createWaveform( - new long[]{10, 10_000}, new int[]{255, 0}, -1); + new long[]{10, 10_000}, new int[]{128, 255}, -1); vibrate(service, alarmEffect, ALARM_ATTRS); - // VibrationThread will start this vibration async, wait until it has started. - assertTrue(waitUntil(s -> !fakeVibrator.getAllEffectSegments().isEmpty(), service, + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), @@ -1053,23 +1070,24 @@ public class VibratorManagerServiceTest { // The second vibration shouldn't have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // The second vibration shouldn't have played any prebaked segment. - assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream() + assertFalse(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); - cancelVibrate(service); // Clean up long effect. } @Test public void vibrate_withOngoingHigherImportanceVibration_ignoresEffect() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect effect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, -1); + new long[]{10, 10_000}, new int[]{128, 255}, -1); vibrate(service, effect, ALARM_ATTRS); - // VibrationThread will start this vibration async, so wait before checking it started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), @@ -1078,26 +1096,27 @@ public class VibratorManagerServiceTest { // The second vibration shouldn't have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // The second vibration shouldn't have played any prebaked segment. - assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream() + assertFalse(fakeVibrator.getAllEffectSegments().stream() .anyMatch(PrebakedSegment.class::isInstance)); - cancelVibrate(service); // Clean up long effect. } @Test public void vibrate_withOngoingLowerImportanceVibration_cancelsOngoingEffect() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); - mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK); VibratorManagerService service = createSystemReadyService(); VibrationEffect effect = VibrationEffect.createWaveform( - new long[]{10_000, 10_000}, new int[]{128, 255}, -1); + new long[]{10, 10_000}, new int[]{128, 255}, -1); vibrate(service, effect, HAPTIC_FEEDBACK_ATTRS); - // VibrationThread will start this vibration async, so wait before checking it started. - assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), - service, TEST_TIMEOUT_MILLIS)); + // VibrationThread will start this vibration async. + // Wait until second step started to ensure the noteVibratorOn was triggered. + assertTrue(waitUntil(s -> fakeVibrator.getAmplitudes().size() == 2, service, + TEST_TIMEOUT_MILLIS)); vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS); @@ -1105,10 +1124,8 @@ public class VibratorManagerServiceTest { // The second vibration should have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); // One segment played is the prebaked CLICK from the second vibration. - assertEquals(1, - mVibratorProviders.get(1).getAllEffectSegments().stream() - .filter(PrebakedSegment.class::isInstance) - .count()); + assertEquals(1, fakeVibrator.getAllEffectSegments().stream() + .filter(PrebakedSegment.class::isInstance).count()); } @Test @@ -1139,10 +1156,8 @@ public class VibratorManagerServiceTest { // The new vibration should have recorded that the vibrators were turned on. verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); // One segment played is the prebaked CLICK from the new vibration. - assertEquals(1, - mVibratorProviders.get(1).getAllEffectSegments().stream() - .filter(PrebakedSegment.class::isInstance) - .count()); + assertEquals(1, mVibratorProviders.get(1).getAllEffectSegments().stream() + .filter(PrebakedSegment.class::isInstance).count()); } @Test @@ -1153,8 +1168,9 @@ public class VibratorManagerServiceTest { .build(); mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); - mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK); VibratorManagerService service = createSystemReadyService(); VibrationEffect effect = VibrationEffect.createWaveform( @@ -1173,7 +1189,7 @@ public class VibratorManagerServiceTest { verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); // One step segment (with several amplitudes) and one click should have played. Notably // there is no primitive segment. - List<VibrationEffectSegment> played = mVibratorProviders.get(1).getAllEffectSegments(); + List<VibrationEffectSegment> played = fakeVibrator.getAllEffectSegments(); assertEquals(2, played.size()); assertEquals(1, played.stream().filter(StepSegment.class::isInstance).count()); assertEquals(1, played.stream().filter(PrebakedSegment.class::isInstance).count()); @@ -1182,8 +1198,9 @@ public class VibratorManagerServiceTest { @Test public void vibrate_withInputDevices_vibratesInputDevices() throws Exception { mockVibrators(1); - mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK); + FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); + fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); + fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK); when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); when(mIInputManagerMock.getVibratorIds(eq(1))).thenReturn(new int[]{1}); when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn(createInputDeviceWithVibrator(1)); @@ -1198,7 +1215,7 @@ public class VibratorManagerServiceTest { vibrateAndWaitUntilFinished(service, effect, ALARM_ATTRS); verify(mIInputManagerMock).vibrateCombined(eq(1), eq(effect), any()); - assertTrue(mVibratorProviders.get(1).getAllEffectSegments().isEmpty()); + assertTrue(fakeVibrator.getAllEffectSegments().isEmpty()); } @Test @@ -1497,8 +1514,6 @@ public class VibratorManagerServiceTest { // Alarm vibration will be scaled with SCALE_NONE. assertEquals(1f, ((PrimitiveSegment) fakeVibrator.getAllEffectSegments().get(2)).getScale(), 1e-5); - - cancelVibrate(service); // Clean up long-ish effect. } @Test @@ -1533,8 +1548,6 @@ public class VibratorManagerServiceTest { assertEquals(1, fakeVibrator.getAllEffectSegments().size()); assertEquals(defaultAmplitude / 255f, fakeVibrator.getAmplitudes().get(0), 1e-5); - - cancelVibrate(service); // Clean up long-ish effect. } @Test @@ -1570,7 +1583,6 @@ public class VibratorManagerServiceTest { // Vibration is not stopped nearly after updating service. assertFalse(waitUntil(s -> !s.isVibrating(1), service, 50)); - cancelVibrate(service); // Clean up long effect. } @Test @@ -1596,8 +1608,6 @@ public class VibratorManagerServiceTest { HAPTIC_FEEDBACK_ATTRS); // Haptic feedback played normally when it's from the default device. assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS)); - - cancelVibrate(service); // Clean up long-ish effect. } @Test @@ -1854,9 +1864,7 @@ public class VibratorManagerServiceTest { assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); // Vibration is not cancelled. - assertFalse(waitUntil(s -> !s.isVibrating(1), service, CLEANUP_TIMEOUT_MILLIS)); assertEquals(Arrays.asList(false), mVibratorProviders.get(1).getExternalControlStates()); - cancelVibrate(service); // Clean up long effect. } @Test @@ -1910,9 +1918,7 @@ public class VibratorManagerServiceTest { assertEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); // Vibration is not cancelled. - assertFalse(waitUntil(s -> !s.isVibrating(1), service, CLEANUP_TIMEOUT_MILLIS)); assertEquals(Arrays.asList(false), mVibratorProviders.get(1).getExternalControlStates()); - cancelVibrate(service); // Clean up long effect. } @Test @@ -2536,29 +2542,29 @@ public class VibratorManagerServiceTest { private HalVibration vibrateAndWaitUntilFinished(VibratorManagerService service, CombinedVibration effect, VibrationAttributes attrs) throws InterruptedException { - HalVibration vib = - service.vibrateWithPermissionCheck(UID, Context.DEVICE_ID_DEFAULT, PACKAGE_NAME, - effect, attrs, "some reason", service); + HalVibration vib = vibrate(service, effect, attrs); if (vib != null) { vib.waitForEnd(); } - return vib; } - private void vibrate(VibratorManagerService service, VibrationEffect effect, + private HalVibration vibrate(VibratorManagerService service, VibrationEffect effect, VibrationAttributes attrs) { - vibrate(service, CombinedVibration.createParallel(effect), attrs); + return vibrate(service, CombinedVibration.createParallel(effect), attrs); } - private void vibrate(VibratorManagerService service, CombinedVibration effect, + private HalVibration vibrate(VibratorManagerService service, CombinedVibration effect, VibrationAttributes attrs) { - vibrateWithDevice(service, Context.DEVICE_ID_DEFAULT, effect, attrs); + return vibrateWithDevice(service, Context.DEVICE_ID_DEFAULT, effect, attrs); } - private void vibrateWithDevice(VibratorManagerService service, int deviceId, + private HalVibration vibrateWithDevice(VibratorManagerService service, int deviceId, CombinedVibration effect, VibrationAttributes attrs) { - service.vibrate(UID, deviceId, PACKAGE_NAME, effect, attrs, "some reason", service); + HalVibration vib = service.vibrateWithPermissionCheck(UID, deviceId, PACKAGE_NAME, effect, + attrs, "some reason", service); + mPendingVibrations.add(vib); + return vib; } private boolean waitUntil(Predicate<VibratorManagerService> predicate, diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java index 391220669f2f..2a010f0a82a9 100644 --- a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java +++ b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorController.java @@ -18,7 +18,10 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.frameworks.vibrator.IVibratorController; +import android.frameworks.vibrator.VibrationParam; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.os.VibrationAttributes; @@ -28,17 +31,42 @@ import android.os.VibrationAttributes; */ public final class FakeVibratorController extends IVibratorController.Stub { + private final Handler mHandler; + private VibratorControlService mVibratorControlService; + private VibrationParam[] mRequestResult = new VibrationParam[0]; + public boolean isLinkedToDeath = false; public boolean didRequestVibrationParams = false; public int requestVibrationType = VibrationAttributes.USAGE_UNKNOWN; public long requestTimeoutInMillis = 0; + public FakeVibratorController(Looper looper) { + mHandler = new Handler(looper); + } + + public void setVibratorControlService(VibratorControlService service) { + mVibratorControlService = service; + } + + public void setRequestResult(VibrationParam... params) { + mRequestResult = params; + } + @Override - public void requestVibrationParams(int vibrationType, long timeoutInMillis, IBinder iBinder) + public void requestVibrationParams(int vibrationType, long timeoutInMillis, IBinder token) throws RemoteException { didRequestVibrationParams = true; requestVibrationType = vibrationType; requestTimeoutInMillis = timeoutInMillis; + mHandler.post(() -> { + if (mVibratorControlService != null) { + try { + mVibratorControlService.onRequestVibrationParamsComplete(token, mRequestResult); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + }); } @Override |