Merge "Split long ramps to fit HAL PWLE primitive limit" into sc-dev
This commit is contained in:
@@ -22,6 +22,7 @@ import android.os.vibrator.RampSegment;
|
|||||||
import android.os.vibrator.StepSegment;
|
import android.os.vibrator.StepSegment;
|
||||||
import android.os.vibrator.VibrationEffectSegment;
|
import android.os.vibrator.VibrationEffectSegment;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,6 +60,7 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter
|
|||||||
convertStepsToRamps(segments);
|
convertStepsToRamps(segments);
|
||||||
int newRepeatIndex = addRampDownToZeroAmplitudeSegments(segments, repeatIndex);
|
int newRepeatIndex = addRampDownToZeroAmplitudeSegments(segments, repeatIndex);
|
||||||
newRepeatIndex = addRampDownToLoop(segments, newRepeatIndex);
|
newRepeatIndex = addRampDownToLoop(segments, newRepeatIndex);
|
||||||
|
newRepeatIndex = splitLongRampSegments(info, segments, newRepeatIndex);
|
||||||
return newRepeatIndex;
|
return newRepeatIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,11 +212,70 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter
|
|||||||
return repeatIndex;
|
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) {
|
private static RampSegment apply(StepSegment segment) {
|
||||||
return new RampSegment(segment.getAmplitude(), segment.getAmplitude(),
|
return new RampSegment(segment.getAmplitude(), segment.getAmplitude(),
|
||||||
segment.getFrequency(), segment.getFrequency(), (int) segment.getDuration());
|
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) {
|
private static RampSegment createRampDown(float amplitude, float frequency, long duration) {
|
||||||
return new RampSegment(amplitude, /* endAmplitude= */ 0, frequency, frequency,
|
return new RampSegment(amplitude, /* endAmplitude= */ 0, frequency, frequency,
|
||||||
(int) duration);
|
(int) duration);
|
||||||
@@ -244,4 +305,19 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter
|
|||||||
}
|
}
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,38 @@ public class StepToRampAdapterTest {
|
|||||||
assertEquals(originalSegments, segments);
|
assertEquals(originalSegments, segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
@Test
|
||||||
public void testStepAndRampSegments_withoutPwleCapability_keepsListUnchanged() {
|
public void testStepAndRampSegments_withoutPwleCapability_keepsListUnchanged() {
|
||||||
mAdapter = new StepToRampAdapter(50);
|
mAdapter = new StepToRampAdapter(50);
|
||||||
|
|||||||
Reference in New Issue
Block a user