diff options
| author | 2021-06-23 22:53:10 +0000 | |
|---|---|---|
| committer | 2021-06-23 22:53:10 +0000 | |
| commit | a6689c521a4e9160aa0187423deecb1b17dc99c8 (patch) | |
| tree | baf2296fd0c5e52baadf90d8e495d8d84578fefa | |
| parent | 0c9176bc1d78c7fae7af88f837a5d6c639d295ba (diff) | |
| parent | 885432037f140d48905de59556cb2c78c5398d0a (diff) | |
Merge "Split long ramps to fit HAL PWLE primitive limit" into sc-dev
| -rw-r--r-- | services/core/java/com/android/server/vibrator/StepToRampAdapter.java | 76 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java | 32 |
2 files changed, 108 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java index d439b94ec2fc..1d8c64bddd49 100644 --- a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java +++ b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java @@ -22,6 +22,7 @@ import android.os.vibrator.RampSegment; import android.os.vibrator.StepSegment; import android.os.vibrator.VibrationEffectSegment; +import java.util.ArrayList; import java.util.List; /** @@ -59,6 +60,7 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter convertStepsToRamps(segments); int newRepeatIndex = addRampDownToZeroAmplitudeSegments(segments, repeatIndex); newRepeatIndex = addRampDownToLoop(segments, newRepeatIndex); + newRepeatIndex = splitLongRampSegments(info, segments, newRepeatIndex); return newRepeatIndex; } @@ -210,11 +212,70 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter return repeatIndex; } + /** + * Split {@link RampSegment} entries that have duration longer than {@link + * VibratorInfo#getPwlePrimitiveDurationMax()}. + */ + private int splitLongRampSegments(VibratorInfo info, List<VibrationEffectSegment> segments, + int repeatIndex) { + int maxDuration = info.getPwlePrimitiveDurationMax(); + if (maxDuration <= 0) { + // No limit set to PWLE primitive duration. + return repeatIndex; + } + + int segmentCount = segments.size(); + for (int i = 0; i < segmentCount; i++) { + if (!(segments.get(i) instanceof RampSegment)) { + continue; + } + RampSegment ramp = (RampSegment) segments.get(i); + int splits = ((int) ramp.getDuration() + maxDuration - 1) / maxDuration; + if (splits <= 1) { + continue; + } + segments.remove(i); + segments.addAll(i, splitRampSegment(ramp, splits)); + int addedSegments = splits - 1; + if (repeatIndex > i) { + repeatIndex += addedSegments; + } + i += addedSegments; + segmentCount += addedSegments; + } + + return repeatIndex; + } + private static RampSegment apply(StepSegment segment) { return new RampSegment(segment.getAmplitude(), segment.getAmplitude(), segment.getFrequency(), segment.getFrequency(), (int) segment.getDuration()); } + private static List<RampSegment> splitRampSegment(RampSegment ramp, int splits) { + List<RampSegment> ramps = new ArrayList<>(splits); + long splitDuration = ramp.getDuration() / splits; + float previousAmplitude = ramp.getStartAmplitude(); + float previousFrequency = ramp.getStartFrequency(); + long accumulatedDuration = 0; + + for (int i = 1; i < splits; i++) { + accumulatedDuration += splitDuration; + RampSegment rampSplit = new RampSegment( + previousAmplitude, interpolateAmplitude(ramp, accumulatedDuration), + previousFrequency, interpolateFrequency(ramp, accumulatedDuration), + (int) splitDuration); + ramps.add(rampSplit); + previousAmplitude = rampSplit.getEndAmplitude(); + previousFrequency = rampSplit.getEndFrequency(); + } + + ramps.add(new RampSegment(previousAmplitude, ramp.getEndAmplitude(), previousFrequency, + ramp.getEndFrequency(), (int) (ramp.getDuration() - accumulatedDuration))); + + return ramps; + } + private static RampSegment createRampDown(float amplitude, float frequency, long duration) { return new RampSegment(amplitude, /* endAmplitude= */ 0, frequency, frequency, (int) duration); @@ -244,4 +305,19 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter } return false; } + + private static float interpolateAmplitude(RampSegment ramp, long duration) { + return interpolate(ramp.getStartAmplitude(), ramp.getEndAmplitude(), duration, + ramp.getDuration()); + } + + private static float interpolateFrequency(RampSegment ramp, long duration) { + return interpolate(ramp.getStartFrequency(), ramp.getEndFrequency(), duration, + ramp.getDuration()); + } + + private static float interpolate(float start, float end, long duration, long totalDuration) { + float position = (float) duration / totalDuration; + return start + position * (end - start); + } } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java index f4eb2ded5a9d..32988efbab2c 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java @@ -68,6 +68,38 @@ public class StepToRampAdapterTest { } @Test + public void testRampSegments_withPwleDurationLimit_splitsLongRamps() { + List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, + /* startFrequency= */ 0, /* endFrequency= */ -1, /* duration= */ 25), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude*/ 1, + /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 5))); + List<VibrationEffectSegment> expectedSegments = Arrays.asList( + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, + /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0.32f, + /* startFrequency= */ 0, /* endFrequency= */ -0.32f, /* duration= */ 8), + new RampSegment(/* startAmplitude= */ 0.32f, /* endAmplitude= */ 0.64f, + /* startFrequency= */ -0.32f, /* endFrequency= */ -0.64f, + /* duration= */ 8), + new RampSegment(/* startAmplitude= */ 0.64f, /* endAmplitude= */ 1, + /* startFrequency= */ -0.64f, /* endFrequency= */ -1, /* duration= */ 9), + new RampSegment(/* startAmplitude= */ 1, /* endAmplitude*/ 1, + /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 5)); + + VibratorInfo vibratorInfo = new VibratorInfo.Builder(0) + .setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS) + .setPwlePrimitiveDurationMax(10) + .build(); + + // Update repeat index to skip the ramp splits. + assertEquals(4, mAdapter.apply(segments, 2, vibratorInfo)); + assertEquals(expectedSegments, segments); + } + + @Test public void testStepAndRampSegments_withoutPwleCapability_keepsListUnchanged() { mAdapter = new StepToRampAdapter(50); |