Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b72bec18 authored by Lais Andrade's avatar Lais Andrade
Browse files

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
parent 80348b5b
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -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;
    }

+62 −14
Original line number Diff line number Diff line
@@ -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.
    }