Loading services/core/java/com/android/server/vibrator/VibratorManagerService.java +13 −4 Original line number Diff line number Diff line Loading @@ -603,12 +603,21 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Repeating vibrations always take precedence. return null; } if (mCurrentVibration != null && mCurrentVibration.getVibration().isRepeating()) { if (mCurrentVibration != null) { if (mCurrentVibration.getVibration().attrs.getUsage() == VibrationAttributes.USAGE_ALARM) { if (DEBUG) { Slog.d(TAG, "Ignoring incoming vibration in favor of previous alarm vibration"); Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration"); } return Vibration.Status.IGNORED_FOR_ALARM; } if (mCurrentVibration.getVibration().isRepeating()) { if (DEBUG) { Slog.d(TAG, "Ignoring incoming vibration in favor of repeating vibration"); } return Vibration.Status.IGNORED_FOR_ONGOING; } } return null; } Loading services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java +62 −14 Original line number Diff line number Diff line Loading @@ -565,6 +565,54 @@ public class VibratorManagerServiceTest { eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString()); } @Test public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception { mockVibrators(1); mVibratorProviders.get(1).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()); // VibrationThread will start this vibration async, so wait before checking it started. assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getEffectSegments().isEmpty(), service, TEST_TIMEOUT_MILLIS)); vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), new VibrationAttributes.Builder().setUsage( VibrationAttributes.USAGE_TOUCH).build()); // Wait before checking it never played a second effect. assertFalse(waitUntil(s -> mVibratorProviders.get(1).getEffectSegments().size() > 1, service, /* timeout= */ 50)); } @Test public void vibrate_withOngoingAlarmVibration_ignoresEffect() throws Exception { mockVibrators(1); mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect alarmEffect = VibrationEffect.createWaveform( new long[]{10_000, 10_000}, new int[]{128, 255}, -1); vibrate(service, alarmEffect, new VibrationAttributes.Builder().setUsage( VibrationAttributes.USAGE_ALARM).build()); // VibrationThread will start this vibration async, so wait before checking it started. assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getEffectSegments().isEmpty(), service, TEST_TIMEOUT_MILLIS)); vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), new VibrationAttributes.Builder().setUsage( VibrationAttributes.USAGE_TOUCH).build()); // Wait before checking it never played a second effect. assertFalse(waitUntil(s -> mVibratorProviders.get(1).getEffectSegments().size() > 1, service, /* timeout= */ 50)); } @Test public void vibrate_withInputDevices_vibratesInputDevices() throws Exception { mockVibrators(1); Loading Loading @@ -761,22 +809,22 @@ public class VibratorManagerServiceTest { fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK); VibratorManagerService service = createSystemReadyService(); vibrate(service, CombinedVibrationEffect.startSynced() .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK)) .combine(), ALARM_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1, service, TEST_TIMEOUT_MILLIS)); vibrate(service, CombinedVibrationEffect.startSequential() .addNext(1, VibrationEffect.createOneShot(20, 100)) .combine(), NOTIFICATION_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 2, assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1, service, TEST_TIMEOUT_MILLIS)); vibrate(service, VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f) .compose(), HAPTIC_FEEDBACK_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 3, service, TEST_TIMEOUT_MILLIS)); vibrate(service, CombinedVibrationEffect.startSynced() .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK)) .combine(), ALARM_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 4, service, TEST_TIMEOUT_MILLIS)); Loading @@ -785,17 +833,17 @@ public class VibratorManagerServiceTest { assertEquals(4, fakeVibrator.getEffectSegments().size()); assertEquals(1, fakeVibrator.getAmplitudes().size()); // Alarm vibration is always VIBRATION_INTENSITY_HIGH. PrebakedSegment expected = new PrebakedSegment( VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG); assertEquals(expected, fakeVibrator.getEffectSegments().get(0)); // Notification vibrations will be scaled with SCALE_VERY_HIGH. assertTrue(0.6 < fakeVibrator.getAmplitudes().get(0)); // Haptic feedback vibrations will be scaled with SCALE_LOW. assertTrue(0.5 < ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale()); assertTrue(0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(3)).getScale()); assertTrue(0.5 < ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(1)).getScale()); assertTrue(0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale()); // Alarm vibration is always VIBRATION_INTENSITY_HIGH. PrebakedSegment expected = new PrebakedSegment( VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG); assertEquals(expected, fakeVibrator.getEffectSegments().get(3)); // Ring vibrations have intensity OFF and are not played. } Loading Loading
services/core/java/com/android/server/vibrator/VibratorManagerService.java +13 −4 Original line number Diff line number Diff line Loading @@ -603,12 +603,21 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Repeating vibrations always take precedence. return null; } if (mCurrentVibration != null && mCurrentVibration.getVibration().isRepeating()) { if (mCurrentVibration != null) { if (mCurrentVibration.getVibration().attrs.getUsage() == VibrationAttributes.USAGE_ALARM) { if (DEBUG) { Slog.d(TAG, "Ignoring incoming vibration in favor of previous alarm vibration"); Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration"); } return Vibration.Status.IGNORED_FOR_ALARM; } if (mCurrentVibration.getVibration().isRepeating()) { if (DEBUG) { Slog.d(TAG, "Ignoring incoming vibration in favor of repeating vibration"); } return Vibration.Status.IGNORED_FOR_ONGOING; } } return null; } Loading
services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java +62 −14 Original line number Diff line number Diff line Loading @@ -565,6 +565,54 @@ public class VibratorManagerServiceTest { eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString()); } @Test public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception { mockVibrators(1); mVibratorProviders.get(1).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()); // VibrationThread will start this vibration async, so wait before checking it started. assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getEffectSegments().isEmpty(), service, TEST_TIMEOUT_MILLIS)); vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), new VibrationAttributes.Builder().setUsage( VibrationAttributes.USAGE_TOUCH).build()); // Wait before checking it never played a second effect. assertFalse(waitUntil(s -> mVibratorProviders.get(1).getEffectSegments().size() > 1, service, /* timeout= */ 50)); } @Test public void vibrate_withOngoingAlarmVibration_ignoresEffect() throws Exception { mockVibrators(1); mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect alarmEffect = VibrationEffect.createWaveform( new long[]{10_000, 10_000}, new int[]{128, 255}, -1); vibrate(service, alarmEffect, new VibrationAttributes.Builder().setUsage( VibrationAttributes.USAGE_ALARM).build()); // VibrationThread will start this vibration async, so wait before checking it started. assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getEffectSegments().isEmpty(), service, TEST_TIMEOUT_MILLIS)); vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), new VibrationAttributes.Builder().setUsage( VibrationAttributes.USAGE_TOUCH).build()); // Wait before checking it never played a second effect. assertFalse(waitUntil(s -> mVibratorProviders.get(1).getEffectSegments().size() > 1, service, /* timeout= */ 50)); } @Test public void vibrate_withInputDevices_vibratesInputDevices() throws Exception { mockVibrators(1); Loading Loading @@ -761,22 +809,22 @@ public class VibratorManagerServiceTest { fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK); VibratorManagerService service = createSystemReadyService(); vibrate(service, CombinedVibrationEffect.startSynced() .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK)) .combine(), ALARM_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1, service, TEST_TIMEOUT_MILLIS)); vibrate(service, CombinedVibrationEffect.startSequential() .addNext(1, VibrationEffect.createOneShot(20, 100)) .combine(), NOTIFICATION_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 2, assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1, service, TEST_TIMEOUT_MILLIS)); vibrate(service, VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f) .compose(), HAPTIC_FEEDBACK_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 3, service, TEST_TIMEOUT_MILLIS)); vibrate(service, CombinedVibrationEffect.startSynced() .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK)) .combine(), ALARM_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 4, service, TEST_TIMEOUT_MILLIS)); Loading @@ -785,17 +833,17 @@ public class VibratorManagerServiceTest { assertEquals(4, fakeVibrator.getEffectSegments().size()); assertEquals(1, fakeVibrator.getAmplitudes().size()); // Alarm vibration is always VIBRATION_INTENSITY_HIGH. PrebakedSegment expected = new PrebakedSegment( VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG); assertEquals(expected, fakeVibrator.getEffectSegments().get(0)); // Notification vibrations will be scaled with SCALE_VERY_HIGH. assertTrue(0.6 < fakeVibrator.getAmplitudes().get(0)); // Haptic feedback vibrations will be scaled with SCALE_LOW. assertTrue(0.5 < ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale()); assertTrue(0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(3)).getScale()); assertTrue(0.5 < ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(1)).getScale()); assertTrue(0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale()); // Alarm vibration is always VIBRATION_INTENSITY_HIGH. PrebakedSegment expected = new PrebakedSegment( VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG); assertEquals(expected, fakeVibrator.getEffectSegments().get(3)); // Ring vibrations have intensity OFF and are not played. } Loading