From b72bec18693e9471ace635467f127ad918a60837 Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Mon, 29 Mar 2021 17:01:46 +0000 Subject: [PATCH] Ignore new vibrations for ongoing alarm vibrations The current check to ignore incoming vibrations in favor of ongoing alarm vibrations is relying on the fact that the alarm vibration is repeating. This cl also adds a check for the vibration attributes usage. Fix: 182369095 Test: atest VibratorManagerServiceTest Change-Id: I07113ba2c7b1f8005c27466a80651f0f19699d68 --- .../vibrator/VibratorManagerService.java | 17 ++++- .../vibrator/VibratorManagerServiceTest.java | 76 +++++++++++++++---- 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index b1d6050f82c2d..6bd7198f3c5b5 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -603,11 +603,20 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Repeating vibrations always take precedence. return null; } - if (mCurrentVibration != null && mCurrentVibration.getVibration().isRepeating()) { - if (DEBUG) { - Slog.d(TAG, "Ignoring incoming vibration in favor of previous alarm vibration"); + if (mCurrentVibration != null) { + if (mCurrentVibration.getVibration().attrs.getUsage() + == VibrationAttributes.USAGE_ALARM) { + if (DEBUG) { + 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 Vibration.Status.IGNORED_FOR_ALARM; } return null; } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java index 12ced388d5f77..b0e8ef0bdffe4 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -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); @@ -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)); @@ -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. }