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

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

Fix RampDownAdapter handling repeating waveforms

The adapter replaces the zero-amplitude steps with a ramp down to zero
on devices with configured ramp down duration, but does not handle well
the repeat index and ends up repeating to a part of a ramp introduced.

This fixes the repeat index handling and also the edge case when the
replaced zero segment is the one it starts repeating.

Fix: 198755610
Test: RampDownAdapterTest
Change-Id: I2489b1a73088f2b992455f2b687daf5c54298dd1
parent 637cc7dc
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -77,9 +77,8 @@ final class RampDownAdapter implements VibrationEffectAdapters.SegmentsAdapter<V
     */
    private int addRampDownToZeroAmplitudeSegments(List<VibrationEffectSegment> segments,
            int repeatIndex) {
        int newRepeatIndex = repeatIndex;
        int newSegmentCount = segments.size();
        for (int i = 1; i < newSegmentCount; i++) {
        int segmentCount = segments.size();
        for (int i = 1; i < segmentCount; i++) {
            VibrationEffectSegment previousSegment = segments.get(i - 1);
            if (!isOffSegment(segments.get(i))
                    || !endsWithNonZeroAmplitude(previousSegment)) {
@@ -116,16 +115,23 @@ final class RampDownAdapter implements VibrationEffectAdapters.SegmentsAdapter<V
            if (replacementSegments != null) {
                int segmentsAdded = replacementSegments.size() - 1;

                segments.remove(i);
                VibrationEffectSegment originalOffSegment = segments.remove(i);
                segments.addAll(i, replacementSegments);
                if (repeatIndex > i) {
                    newRepeatIndex += segmentsAdded;
                if (repeatIndex >= i) {
                    if (repeatIndex == i) {
                        // This effect is repeating to the removed off segment: add it back at the
                        // end of the vibration so the loop timings are preserved, and skip it.
                        segments.add(originalOffSegment);
                        repeatIndex++;
                        segmentCount++;
                    }
                    repeatIndex += segmentsAdded;
                }
                i += segmentsAdded;
                newSegmentCount += segmentsAdded;
                segmentCount += segmentsAdded;
            }
        }
        return newRepeatIndex;
        return repeatIndex;
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -1040,7 +1040,7 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
            newSegments.remove(segmentIndex);
            newSegments.addAll(segmentIndex, fallback.getSegments());
            if (segmentIndex < effect.getRepeatIndex()) {
                newRepeatIndex += fallback.getSegments().size();
                newRepeatIndex += fallback.getSegments().size() - 1;
            }
            return new VibrationEffect.Composed(newSegments, newRepeatIndex);
        }
+62 −7
Original line number Diff line number Diff line
@@ -103,21 +103,18 @@ public class RampDownAdapterTest {
    public void testStepSegments_withShortZeroSegment_replaceWithStepsDown() {
        List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)));
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10)));
        List<VibrationEffectSegment> expectedSegments = Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100));

        assertEquals(1, mAdapter.apply(segments, 1, TEST_VIBRATOR_INFO));
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5));

        assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
        assertEquals(expectedSegments, segments);
    }

    @Test
    public void testStepSegments_withLongZeroSegment_replaceWithStepsDown() {
    public void testStepSegments_withLongZeroSegment_replaceWithStepsDownWithRemainingOffSegment() {
        List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
@@ -131,9 +128,67 @@ public class RampDownAdapterTest {
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35),
                new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100));

        assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
        assertEquals(expectedSegments, segments);
    }

    @Test
    public void testStepSegments_withZeroSegmentBeforeRepeat_fixesRepeat() {
        List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 50),
                new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)));
        List<VibrationEffectSegment> expectedSegments = Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35),
                new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100));

        // Repeat index fixed after intermediate steps added
        assertEquals(5, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
        assertEquals(expectedSegments, segments);
    }

    @Test
    public void testStepSegments_withZeroSegmentAfterRepeat_preservesRepeat() {
        List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)));
        List<VibrationEffectSegment> expectedSegments = Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100));

        assertEquals(3, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
        assertEquals(expectedSegments, segments);
    }

    @Test
    public void testStepSegments_withZeroSegmentAtRepeat_fixesRepeatAndAppendOriginalToListEnd() {
        List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 50),
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 100)));
        List<VibrationEffectSegment> expectedSegments = Arrays.asList(
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
                new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35),
                new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 100),
                // Original zero segment appended to the end of new looping vibration,
                // then converted to ramp down as well.
                new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5),
                new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35));

        // Repeat index fixed after intermediate steps added
        assertEquals(5, mAdapter.apply(segments, 1, TEST_VIBRATOR_INFO));
        assertEquals(expectedSegments, segments);
    }